Added format SoftNi sub + working on CaptionInc

git-svn-id: https://subtitleedit.googlecode.com/svn/trunk@1184 99eadd0c-20b8-1223-b5c4-2a2b2df33de2
This commit is contained in:
niksedk 2012-05-15 19:34:08 +00:00
parent 0cf424323c
commit 77d929cf12
9 changed files with 409 additions and 27 deletions

View File

@ -15,6 +15,8 @@ namespace Nikse.SubtitleEdit.Forms
private string _wavFileName = null;
private string _spectrogramDirectory;
public List<Bitmap> SpectrogramBitmaps { get; private set; }
private string _encodeParamters;
private const string RetryEncodeParameters = "acodec=s16l";
public AddWareForm()
{
@ -34,6 +36,7 @@ namespace Nikse.SubtitleEdit.Forms
buttonCancel.Text = Configuration.Settings.Language.General.Cancel;
labelSourcevideoFile.Text = Configuration.Settings.Language.AddWaveForm.SourceVideoFile;
_spectrogramDirectory = spectrogramDirectory;
_encodeParamters = Configuration.Settings.General.VlcWaveTranscodeSettings;
}
private void buttonRipWave_Click(object sender, EventArgs e)
@ -44,7 +47,7 @@ namespace Nikse.SubtitleEdit.Forms
SourceVideoFileName = labelVideoFileName.Text;
string targetFile = Path.GetTempFileName() + ".wav";
// string parameters = "-I dummy -vvv \"" + SourceVideoFileName + "\" --sout=#transcode{vcodec=none,acodec=s16l}:file{dst=\"" + targetFile + "\"} vlc://quit";
string parameters = "-I dummy -vvv --no-sout-video --sout #transcode{" + Configuration.Settings.General.VlcWaveTranscodeSettings + "}:std{mux=wav,access=file,dst=\"" + targetFile + "\"} \"" + SourceVideoFileName + "\" vlc://quit";
string parameters = "-I dummy -vvv --no-sout-video --sout #transcode{" + _encodeParamters + "}:std{mux=wav,access=file,dst=\"" + targetFile + "\"} \"" + SourceVideoFileName + "\" vlc://quit";
@ -52,7 +55,7 @@ namespace Nikse.SubtitleEdit.Forms
if (Utilities.IsRunningOnLinux() || Utilities.IsRunningOnMac())
{
vlcPath = "cvlc";
parameters = "-vvv --no-sout-video --sout '#transcode{acodec=s16l}:std{mux=wav,access=file,dst=" + targetFile + "}' \"" + SourceVideoFileName + "\" vlc://quit";
parameters = "-vvv --no-sout-video --sout '#transcode{" + _encodeParamters + "}:std{mux=wav,access=file,dst=" + targetFile + "}' \"" + SourceVideoFileName + "\" vlc://quit";
}
else // windows
{
@ -109,6 +112,13 @@ namespace Nikse.SubtitleEdit.Forms
if (!File.Exists(targetFile))
{
if (_encodeParamters != RetryEncodeParameters)
{
_encodeParamters = RetryEncodeParameters;
buttonRipWave_Click(null, null);
return;
}
MessageBox.Show("Could not find extracted wave file! This feature requires VLC media player 1.1.x or newer." + Environment.NewLine
+ Environment.NewLine +
"Command line: " + vlcPath + " " + parameters);

View File

@ -383,7 +383,7 @@ namespace Nikse.SubtitleEdit.Logic
LargeDelayMilliseconds = 5000;
OpenSubtitleExtraExtensions = "*.mp4;*.m4v;*.mkv;"; // matroska/mp4/m4v files (can contain subtitles)
ListViewColumsRememberSize = true;
VlcWaveTranscodeSettings = "acodec=s16l,channels=1,ab=64,samplerate=8000";
VlcWaveTranscodeSettings = "acodec=s16l"; // "acodec=s16l,channels=1,ab=64,samplerate=8000";
UseTimeFormatHHMMSSFF = false;
ShowBetaStuff = false;
}

View File

@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
{
class CaptionsInc : SubtitleFormat
{
public override string Extension
{
get { return ".cin"; }
}
public override string Name
{
get { return "Caption Inc"; }
}
public override bool HasLineNumber
{
get { return false; }
}
public override bool IsTimeBased
{
get { return true; }
}
public void Save(string fileName, Subtitle subtitle)
{
var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
string name = Path.GetFileNameWithoutExtension(fileName);
byte[] buffer = Encoding.ASCII.GetBytes(name);
for (int i = 0; i < buffer.Length && i < 8; i++)
fs.WriteByte(buffer[i]);
while (fs.Length < 8)
fs.WriteByte(0x20);
buffer = Encoding.ASCII.GetBytes("00000617");
fs.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes("00011818");
fs.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes("program description CPC CaptionMaker D");
fs.Write(buffer, 0, buffer.Length);
// paragraphs
foreach (Paragraph p in subtitle.Paragraphs)
{
buffer = new byte[] { 0x0D, 0x0A, 0xFE, 0x30, 0x34, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x31, 0x37, 0x0D, 0x0A, 0x14, 0x20, 0x14, 0x2E, 0x14 };
fs.Write(buffer, 0, buffer.Length);
buffer = Encoding.GetEncoding(1252).GetBytes(p.Text);
fs.Write(buffer, 0, buffer.Length);
buffer = new byte[] { 0x14, 0x2C, 0x14, 0x2F };
fs.Write(buffer, 0, buffer.Length);
//WriteTime(fs, p.StartTime);
//WriteTime(fs, p.EndTime);
}
fs.Close();
}
private void WriteTime(FileStream fs, TimeCode timeCode)
{
fs.WriteByte((byte)timeCode.Hours);
fs.WriteByte((byte)timeCode.Minutes);
fs.WriteByte((byte)timeCode.Seconds);
fs.WriteByte((byte)MillisecondsToFrames(timeCode.Milliseconds));
}
public override bool IsMine(List<string> lines, string fileName)
{
if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
{
if (!fileName.ToLower().EndsWith(".cin"))
return false;
var sub = new Subtitle();
LoadSubtitle(sub, lines, fileName);
return sub.Paragraphs.Count > 0;
}
return false;
}
public override string ToText(Subtitle subtitle, string title)
{
return "Not supported!";
}
private TimeCode DecodeTimeStamp(string timeCode)
{
try
{
return new TimeCode(int.Parse(timeCode.Substring(0, 2)), int.Parse(timeCode.Substring(2, 2)), int.Parse(timeCode.Substring(4, 2)), FramesToMilliseconds(int.Parse(timeCode.Substring(6, 2))));
}
catch (Exception exception)
{
System.Diagnostics.Debug.WriteLine(exception.Message);
return new TimeCode(0, 0, 0, 0);
}
}
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
{
subtitle.Paragraphs.Clear();
subtitle.Header = null;
byte[] buffer = File.ReadAllBytes(fileName);
int i = 256;
Paragraph last = null;
while (i < buffer.Length - 20)
{
var p = new Paragraph();
while (buffer[i] != 0xfe && i < buffer.Length - 20)
{
i++;
}
if (buffer[i] == 0xfe)
{
i += 4;
string startTime = Encoding.ASCII.GetString(buffer, i, 8);
i += 8;
if (Utilities.IsInteger(startTime))
{
p.StartTime = DecodeTimeStamp(startTime);
}
}
bool startFound = false;
bool textEnd = false;
while (!startFound && !textEnd && i < buffer.Length - 20)
{
if (buffer[i] == 0x0d)
i++;
else if (buffer[i] == 0x0a)
;
else if (buffer[i] == 0x14 && buffer[i + 1] == 0x2c) // text end
textEnd = true;
else if (buffer[i] <= 0x20) // text start
i++;
else
startFound = true;
i++;
}
i++;
if (!textEnd)
{
i-=2;
int start = i;
int textLength = 0;
while (!textEnd && i < buffer.Length - 20)
{
if (buffer[i] == 0x14 && buffer[i + 1] == 0x2c) // text end
textEnd = true;
else if (buffer[i] == 0xd && buffer[i + 1] == 0xa) // text end
textEnd = true;
textLength++;
i++;
}
i++;
if (start + textLength < buffer.Length - 10 && textLength > 1)
{
string text = Encoding.GetEncoding(1252).GetString(buffer, start, textLength - 1);
text = text.Replace(Encoding.GetEncoding(1252).GetString(new byte[] { 0x14, 0x70 }, 0, 2), Environment.NewLine);
p.Text = text;
subtitle.Paragraphs.Add(p);
last = p;
}
}
while (i < buffer.Length && buffer[i] != 0xa)
i++;
i++;
if (buffer[i] == 0xfe)
{
string endTime = Encoding.ASCII.GetString(buffer, i+ 4, 8);
if (Utilities.IsInteger(endTime))
{
p.EndTime = DecodeTimeStamp(endTime);
}
}
}
if (last != null && last.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)
last.EndTime.TotalMilliseconds = last.StartTime.TotalMilliseconds + Utilities.GetDisplayMillisecondsFromText(last.Text);
subtitle.Renumber(1);
}
}
}

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
@ -32,35 +32,35 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
{
var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
byte[] buffer = new byte[127];
for (int i = 0; i < buffer.Length; i++)
buffer[i] = 0;
buffer[01] = 0xEA;
buffer[02] = 0x22;
buffer[02] = 0x01;
byte[] buffer = new byte[] { 0xEA, 0x22, 1, 0 }; // header
fs.Write(buffer, 0, buffer.Length);
buffer = new byte[] { 5, 0, 9, 0xA8, 0xAF, 0x4F }; // sizes
fs.Write(buffer, 0, buffer.Length);
for (int i = 0; i < 118; i++)
fs.WriteByte(0);
// paragraphs
foreach (Paragraph p in subtitle.Paragraphs)
{
string text = p.Text.Replace(Environment.NewLine, "\0\0\0\0");
int length = 20 + text.Length;
fs.WriteByte((byte)length);
fs.WriteByte(0x61); // ??
WriteTime(fs, p.StartTime);
WriteTime(fs, p.EndTime);
int length = text.Length + 16;
long end = fs.Position + length;
fs.WriteByte((byte)(length));
fs.WriteByte(0x12); // ??
fs.WriteByte(0x03); // ??
fs.WriteByte(0x00); // ??
fs.WriteByte(0x00); // ??
fs.WriteByte(0x00); // ??
fs.WriteByte(0x00); // ??
fs.WriteByte(0x03); // ??
fs.WriteByte(0x0F); // ??
fs.WriteByte(0x10); // ??
fs.WriteByte(0x42); // ?
WriteTime(fs, p.StartTime);
buffer = new byte[] { 0x12, 1,0,0,0,0,1,0x0F,1 }; // sizes ?
fs.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(text);
fs.Write(buffer, 0, buffer.Length); // Text starter på index 19 (0 baseret)
while (end > fs.Position)
fs.WriteByte(0);
}
fs.Close();
}
@ -77,8 +77,8 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
{
if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
{
FileInfo fi = new FileInfo(fileName);
if (fi.Length >= 640 && fi.Length < 1024000) // not too small or too big
var fi = new FileInfo(fileName);
if (fi.Length >= 200 && fi.Length < 1024000) // not too small or too big
{
if (fileName.ToLower().EndsWith(".cap"))
{
@ -116,7 +116,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
Paragraph last = null;
while (i < buffer.Length - 20)
{
Paragraph p = new Paragraph();
var p = new Paragraph();
int length = buffer[i];
int textLength = length - 20;
int start = 19;
@ -142,6 +142,8 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
subtitle.Paragraphs.Add(p);
last = p;
}
if (length == 0)
length++;
i += length;
}
if (last != null && last.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)

View File

@ -0,0 +1,159 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
{
/// <summary>
/// SoftNi - http://www.softni.com/
/// </summary>
public class SoftNiSub : SubtitleFormat
{
static Regex regexTimeCodes = new Regex(@"^\d\d:\d\d:\d\d\.\d\d\\\d\d:\d\d:\d\d\.\d\d$", RegexOptions.Compiled);
public override string Extension
{
get { return ".sub"; }
}
public override string Name
{
get { return "SoftNi sub"; }
}
public override bool HasLineNumber
{
get { return false; }
}
public override bool IsTimeBased
{
get { return true; }
}
public override bool IsMine(List<string> lines, string fileName)
{
var subtitle = new Subtitle();
DoLoadSubtitle(subtitle, lines);
return subtitle.Paragraphs.Count > _errorCount;
}
public override string ToText(Subtitle subtitle, string title)
{
var sb = new StringBuilder();
sb.AppendLine("*PART 1*");
sb.AppendLine("00:00:00.00\\00:00:00.00");
foreach (Paragraph p in subtitle.Paragraphs)
{
string text = p.Text;
if (text.StartsWith("<i>") && text.EndsWith("</i>"))
text = "[" + text;
text = Utilities.RemoveHtmlTags(text);
sb.AppendLine(string.Format("{0}{1}{2}\\{3}", text, Environment.NewLine, p.StartTime.ToHHMMSSPeriodFF(), p.EndTime.ToHHMMSSPeriodFF()));
}
sb.AppendLine(@"*END*
...........\...........
*CODE*
0000000000000000
*CAST*
*GENERATOR*
*FONTS*
*READ*
0,300 15,000 130,000 100,000 25,000
*TIMING*
1 25 0
*TIMED BACKUP NAME*
C:\
*FORMAT SAMPLE ÅåÉéÌìÕõÛûÿ*
*READ ADVANCED*
< > 1 1 0,300
*MARKERS*");
return sb.ToString();
}
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
{
DoLoadSubtitle(subtitle, lines);
}
private void DoLoadSubtitle(Subtitle subtitle, List<string> lines)
{
//—Peter.
//—Estoy de licencia.
//01:48:50.07\01:48:52.01
var sb = new StringBuilder();
Paragraph p = null;
subtitle.Paragraphs.Clear();
foreach (string line in lines)
{
string s = line.Trim();
if (regexTimeCodes.IsMatch(s))
{
var temp = s.Split('\\');
if (temp.Length > 1)
{
string start = temp[0];
string end = temp[1];
string[] startParts = start.Split(":.".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
string[] endParts = end.Split(":.".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (startParts.Length == 4 && endParts.Length == 4)
{
try
{
p = new Paragraph();
p.StartTime = DecodeTimeCode(startParts);
p.EndTime = DecodeTimeCode(endParts);
string text = sb.ToString().Trim();
if (text.StartsWith("["))
text = "<i>" + text.Remove(0, 1) + "</i>";
p.Text = text;
if (text.Length > 0)
subtitle.Paragraphs.Add(p);
sb = new StringBuilder();
}
catch (Exception exception)
{
_errorCount++;
System.Diagnostics.Debug.WriteLine(exception.Message);
}
}
}
}
else if (line.Trim().Length == 0)
{
// skip empty lines
}
else if (line.StartsWith("*"))
{
// skip start
}
else if (line.Trim().Length > 0 && p != null)
{
sb.AppendLine(line);
}
}
subtitle.Renumber(1);
}
private TimeCode DecodeTimeCode(string[] parts)
{
//00:00:07:12
string hour = parts[0];
string minutes = parts[1];
string seconds = parts[2];
string frames = parts[3];
int milliseconds = (int)((1000.0 / Configuration.Settings.General.CurrentFrameRate) * int.Parse(frames));
if (milliseconds > 999)
milliseconds = 999;
TimeCode tc = new TimeCode(int.Parse(hour), int.Parse(minutes), int.Parse(seconds), milliseconds);
return tc;
}
}
}

View File

@ -66,6 +66,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
new SubViewer20(),
new RhozetHarmonic(),
new Sami(),
new SoftNiSub(),
new Spruce(),
new SpruceWithSpace(),
new StructuredTitles(),

View File

@ -134,6 +134,11 @@ namespace Nikse.SubtitleEdit.Logic
return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", _time.Hours, _time.Minutes, _time.Seconds, SubtitleFormats.SubtitleFormat.MillisecondsToFrames(_time.Milliseconds));
}
public string ToHHMMSSPeriodFF()
{
return string.Format("{0:00}:{1:00}:{2:00}.{3:00}", _time.Hours, _time.Minutes, _time.Seconds, SubtitleFormats.SubtitleFormat.MillisecondsToFrames(_time.Milliseconds));
}
}
}

View File

@ -1337,6 +1337,7 @@ namespace Nikse.SubtitleEdit.Logic
sb.Append("*" + new Spt().Extension + ";");
sb.Append("*" + new Wsb().Extension + ";");
sb.Append("*" + new CheetahCaption().Extension + ";");
sb.Append("*" + new CaptionsInc().Extension + ";");
sb.Append("*" + new SonicScenaristBitmaps().Extension + ";");
sb.Append("*.mks;"); // matroska subtitlefiles (normally contain subtitles)
sb.Append("*.sup;"); // blu-ray sup

View File

@ -613,6 +613,7 @@
<Compile Include="Logic\SubtitleFormats\CapMakerPlus.cs" />
<Compile Include="Logic\SubtitleFormats\Captionate.cs" />
<Compile Include="Logic\SubtitleFormats\CaptionateMs.cs" />
<Compile Include="Logic\SubtitleFormats\CaptionsInc.cs" />
<Compile Include="Logic\SubtitleFormats\CaraokeXml.cs" />
<Compile Include="Logic\SubtitleFormats\Cavena890.cs" />
<Compile Include="Logic\SubtitleFormats\CheetahCaption.cs" />
@ -638,6 +639,7 @@
<Compile Include="Logic\SubtitleFormats\RealTime.cs" />
<Compile Include="Logic\SubtitleFormats\Scenarist.cs" />
<Compile Include="Logic\SubtitleFormats\ScenaristClosedCaptions.cs" />
<Compile Include="Logic\SubtitleFormats\SoftNiSub.cs" />
<Compile Include="Logic\SubtitleFormats\Son.cs" />
<Compile Include="Logic\SubtitleFormats\SonicScenaristBitmaps.cs" />
<Compile Include="Logic\SubtitleFormats\SonyDVDArchitectExplicitDuration.cs" />