Added new subtitle format

This commit is contained in:
niksedk 2014-08-14 21:27:06 +02:00
parent 14461ab1c7
commit 7b22a95f3a
5 changed files with 230 additions and 9 deletions

View File

@ -260,5 +260,47 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
return list;
}
internal static List<string> ReadArray(string text)
{
var list = new List<string>();
text = text.Trim();
if (text.StartsWith("[") && text.EndsWith("]"))
{
text = text.Trim('[');
text = text.Trim(']');
text = text.Trim();
text = text.Replace("<br />", Environment.NewLine);
text = text.Replace("<br>", Environment.NewLine);
text = text.Replace("<br/>", Environment.NewLine);
text = text.Replace("\\n", Environment.NewLine);
bool keepNext = false;
var sb = new StringBuilder();
for (int i = 0; i < text.Length; i++)
{
string s = text.Substring(i, 1);
if (s == "\\" && !keepNext)
{
keepNext = true;
}
else if (!keepNext && s == ",")
{
list.Add(sb.ToString());
sb = new StringBuilder();
keepNext = false;
}
else
{
sb.Append(s);
keepNext = false;
}
}
if (sb.Length > 0)
list.Add(sb.ToString());
}
return list;
}
}
}

View File

@ -0,0 +1,174 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
{
public class JsonType6 : SubtitleFormat
{
public override string Extension
{
get { return ".json"; }
}
public override string Name
{
get { return "JSON Type 6"; }
}
public override bool IsTimeBased
{
get { return true; }
}
public override bool IsMine(List<string> lines, string fileName)
{
var subtitle = new Subtitle();
LoadSubtitle(subtitle, lines, fileName);
return subtitle.Paragraphs.Count > _errorCount;
}
public override string ToText(Subtitle subtitle, string title)
{
var sb = new StringBuilder();
sb.Append("{\"words\":[");
for (int i = 0; i < subtitle.Paragraphs.Count; i++)
{
Paragraph p = subtitle.Paragraphs[i];
//split words
string text = p.Text.Replace(Environment.NewLine, " ").Replace(" ", " ");
var words = text.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var times = GenerateTimes(words, text, p.StartTime, p.EndTime);
for (int j = 0; j < words.Length; j++)
{
sb.Append("[\"");
sb.Append(times[j]);
sb.Append("\",\"");
sb.Append(Json.EncodeJsonText(words[j]));
sb.Append("\"]");
sb.Append(",");
}
var next = subtitle.GetParagraphOrDefault(i + 1);
if (next == null || next.StartTime.TotalMilliseconds - 200 < p.EndTime.TotalMilliseconds)
{
sb.Append("[\"");
sb.Append(Convert.ToInt64(p.EndTime.TotalMilliseconds).ToString());
sb.Append("\",\"");
sb.Append("\"]");
sb.Append(",");
}
}
return sb.ToString().Trim().TrimEnd(',') + "],\"paragraphs\":[],\"speakers\":{}}";
}
private List<string> GenerateTimes(string[] words, string text, TimeCode start, TimeCode end)
{
var list = new List<string>();
double total = 0.0;
for (int i = 0; i < words.Length; i++)
{
string word = words[i];
double percent = (word.Length + 1.0) * 100 / text.Length;
list.Add(Convert.ToInt64(start.TotalMilliseconds + (total * (end.TotalMilliseconds - start.TotalMilliseconds) / 100.0)).ToString());
total += percent;
}
return list;
}
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
{
_errorCount = 0;
var sb = new StringBuilder();
foreach (string s in lines)
sb.Append(s);
var words = Json.ReadArray(sb.ToString(), "words");
foreach (string word in words)
{
var elements = Json.ReadArray(word);
if (elements.Count == 2)
{
string milliseconds = elements[0].Trim('"').Trim();
string text = elements[1].Trim();
if (text.StartsWith("\""))
text = text.Remove(0, 1);
if (text.EndsWith("\""))
text = text.Remove(text.Length - 1, 1);
long number;
if (long.TryParse(milliseconds, out number))
subtitle.Paragraphs.Add(new Paragraph(text, number, number));
else
_errorCount++;
}
}
sb = new StringBuilder();
var sub = new Subtitle();
double startMilliseconds = 0;
if (subtitle.Paragraphs.Count > 0)
startMilliseconds = subtitle.Paragraphs[0].StartTime.TotalMilliseconds;
for (int i = 0; i < subtitle.Paragraphs.Count - 1; i++)
{
Paragraph p = subtitle.Paragraphs[i];
Paragraph next = subtitle.Paragraphs[i + 1];
Paragraph prev = subtitle.GetParagraphOrDefault(i - 1);
if (sb.Length + p.Text.Length > (Configuration.Settings.General.SubtitleLineMaximumLength * 2) - 15) // text too big
{
var newParagraph = new Paragraph(sb.ToString(), startMilliseconds, prev.EndTime.TotalMilliseconds);
sub.Paragraphs.Add(newParagraph);
sb = new StringBuilder();
if (p.Text.Trim().Length > 0)
{
sb.Append(p.Text);
startMilliseconds = p.StartTime.TotalMilliseconds;
}
}
else if (next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds > 2000) // long time to next sub
{
if (p.Text.Trim().Length > 0)
sb.Append(" " + p.Text);
var newParagraph = new Paragraph(sb.ToString(), startMilliseconds, next.StartTime.TotalMilliseconds);
sub.Paragraphs.Add(newParagraph);
sb = new StringBuilder();
startMilliseconds = next.StartTime.TotalMilliseconds;
}
else if (p.Text.Trim().Length == 0) // empty text line
{
if (next.Text.Trim().Length == 0 && sb.Length > 0)
{
var newParagraph = new Paragraph(sb.ToString(), startMilliseconds, next.StartTime.TotalMilliseconds);
sub.Paragraphs.Add(newParagraph);
sb = new StringBuilder();
}
}
else // just add word to current sub
{
if (sb.Length == 0)
startMilliseconds = p.StartTime.TotalMilliseconds;
if (p.Text.Trim().Length > 0)
sb.Append(" " + p.Text);
}
}
if (sb.Length > 0)
{
var newParagraph = new Paragraph(sb.ToString().Trim(), startMilliseconds, Utilities.GetOptimalDisplayMilliseconds(sb.ToString()));
sub.Paragraphs.Add(newParagraph);
}
subtitle.Paragraphs.Clear();
foreach (Paragraph p in sub.Paragraphs)
{
p.Text = Utilities.AutoBreakLine(p.Text);
subtitle.Paragraphs.Add(new Paragraph(p));
}
subtitle.RemoveEmptyLines();
subtitle.Renumber(1);
}
}
}

View File

@ -78,6 +78,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
new JsonType3(),
new JsonType4(),
new JsonType5(),
new JsonType6(),
new Lrc(),
new MicroDvd(),
new MidwayInscriberCGX(),

View File

@ -889,6 +889,7 @@
<Compile Include="Logic\SubtitleFormats\AdobeEncore.cs" />
<Compile Include="Logic\SubtitleFormats\DvdStudioProSpaceOne.cs" />
<Compile Include="Logic\SubtitleFormats\FinalCutProXml14.cs" />
<Compile Include="Logic\SubtitleFormats\JsonType6.cs" />
<Compile Include="Logic\SubtitleFormats\JsonType5.cs" />
<Compile Include="Logic\SubtitleFormats\SatBoxPng.cs" />
<Compile Include="Logic\SubtitleFormats\UnknownSubtitle73.cs" />

View File

@ -666,15 +666,18 @@ Dialogue: Marked=0,0:00:01.00,0:00:03.00,Default,NTP,0000,0000,0000,!Effect," +
int expected = subtitle.Paragraphs.Count;
foreach (SubtitleFormat format in SubtitleFormat.AllSubtitleFormats)
{
format.BatchMode = true;
string text = format.ToText(subtitle, "test");
var list = new List<string>();
foreach (string line in text.Replace("\r\n", "\n").Split('\n'))
list.Add(line);
var s2 = new Subtitle();
format.LoadSubtitle(s2, list, null);
int actual = s2.Paragraphs.Count;
Assert.AreEqual(expected, actual, format.FriendlyName);
if (format.GetType() != typeof(JsonType6))
{
format.BatchMode = true;
string text = format.ToText(subtitle, "test");
var list = new List<string>();
foreach (string line in text.Replace("\r\n", "\n").Split('\n'))
list.Add(line);
var s2 = new Subtitle();
format.LoadSubtitle(s2, list, null);
int actual = s2.Paragraphs.Count;
Assert.AreEqual(expected, actual, format.FriendlyName);
}
}
}