mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-24 20:22:41 +01:00
Add some support for PGS in mkv for "embed subs"
This commit is contained in:
parent
d3cb4c8053
commit
78351ffc2b
@ -1029,6 +1029,7 @@ We leverage the intrinsic rhythm of the image.</CreateSimpleChainingToolTip>
|
||||
<ToggleDefault>Toggle default</ToggleDefault>
|
||||
<Default>Default</Default>
|
||||
<XGeneratedWithEmbeddedSubs>"{0}" generated with embedded subtitles</XGeneratedWithEmbeddedSubs>
|
||||
<DeleteInputVideo>Delete input video file after "Generate"</DeleteInputVideo>
|
||||
</GenerateVideoWithEmbeddedSubs>
|
||||
<GetDictionaries>
|
||||
<Title>Need dictionaries?</Title>
|
||||
|
@ -26,6 +26,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
private string _inputVideoFileName;
|
||||
private StringBuilder _log;
|
||||
private readonly List<VideoPreviewGeneratorSub> _softSubs = new List<VideoPreviewGeneratorSub>();
|
||||
private readonly List<VideoPreviewGeneratorSub> _tracksToDelete = new List<VideoPreviewGeneratorSub>();
|
||||
private bool _promptFFmpegParameters;
|
||||
private readonly List<string> _cleanUpFolders = new List<string>();
|
||||
|
||||
@ -132,7 +133,6 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
_inputVideoFileName = inputVideoFileName;
|
||||
_videoInfo = videoInfo;
|
||||
|
||||
|
||||
using (var matroska = new MatroskaFile(inputVideoFileName))
|
||||
{
|
||||
if (matroska.IsValid)
|
||||
@ -159,6 +159,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
listViewSubtitles.EndUpdate();
|
||||
}
|
||||
|
||||
_tracksToDelete.Clear();
|
||||
}
|
||||
|
||||
private void AddListViewItem(Trak track)
|
||||
@ -185,7 +187,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
var item = new ListViewItem
|
||||
{
|
||||
Tag = sub,
|
||||
Text = sub.SubtitleFormat != null ? sub.SubtitleFormat.Name : sub.Format,
|
||||
Text = sub.SubtitleFormat ?? sub.Format,
|
||||
};
|
||||
item.SubItems.Add(GetDisplayLanguage(sub.Language));
|
||||
item.SubItems.Add(sub.IsDefault.ToString(CultureInfo.InvariantCulture));
|
||||
@ -221,8 +223,24 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
private void AddListViewItem(MatroskaTrackInfo track, MatroskaFile matroska)
|
||||
{
|
||||
if (track.CodecId.Equals("S_HDMV/PGS", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
AddListViewItem(new VideoPreviewGeneratorSub
|
||||
{
|
||||
Name = track.CodecId,
|
||||
Language = track.Language,
|
||||
IsNew = false,
|
||||
IsForced = track.IsForced,
|
||||
IsDefault = track.IsDefault,
|
||||
Tag = track,
|
||||
SubtitleFormat = track.CodecId,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (track.CodecId.Equals("S_VOBSUB", StringComparison.OrdinalIgnoreCase) ||
|
||||
track.CodecId.Equals("S_HDMV/PGS", StringComparison.OrdinalIgnoreCase) ||
|
||||
track.CodecId.Equals("S_HDMV/TEXTST", StringComparison.OrdinalIgnoreCase) ||
|
||||
track.CodecId.Equals("S_DVBSUB", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@ -253,7 +271,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
IsForced = track.IsForced,
|
||||
IsDefault = track.IsDefault,
|
||||
Tag = track,
|
||||
SubtitleFormat = format,
|
||||
SubtitleFormat = format.GetType().Name,
|
||||
FileName = fileName,
|
||||
});
|
||||
}
|
||||
@ -268,19 +286,17 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
if (fileName.EndsWith(".sup", StringComparison.OrdinalIgnoreCase) &&
|
||||
FileUtil.IsBluRaySup(fileName))
|
||||
{
|
||||
MessageBox.Show("FFmpeg does not support embedding of PGS/Blu-ray sup :(");
|
||||
|
||||
//AddListViewItem(new VideoPreviewGeneratorSub
|
||||
//{
|
||||
// Name = Path.GetFileName(fileName),
|
||||
// Language = "eng", //TODO: get from file name or sup
|
||||
// Format = "Blu-ray sup",
|
||||
// SubtitleFormat = null,
|
||||
// IsNew = true,
|
||||
// IsForced = false,
|
||||
// IsDefault = false,
|
||||
// FileName = fileName,
|
||||
//});
|
||||
AddListViewItem(new VideoPreviewGeneratorSub
|
||||
{
|
||||
Name = Path.GetFileName(fileName),
|
||||
Language = GetLanguageFromFileName(fileName),
|
||||
Format = "Blu-ray sup",
|
||||
SubtitleFormat = null,
|
||||
IsNew = true,
|
||||
IsForced = false,
|
||||
IsDefault = false,
|
||||
FileName = fileName,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -301,7 +317,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
Name = Path.GetFileName(fileName),
|
||||
Language = LanguageAutoDetect.AutoDetectGoogleLanguage(subtitle),
|
||||
Format = subtitle.OriginalFormat.FriendlyName,
|
||||
SubtitleFormat = subtitle.OriginalFormat,
|
||||
SubtitleFormat = subtitle.OriginalFormat.GetType().Name,
|
||||
IsNew = true,
|
||||
IsForced = false,
|
||||
IsDefault = false,
|
||||
@ -309,6 +325,41 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
});
|
||||
}
|
||||
|
||||
private static string GetLanguageFromFileName(string fileName)
|
||||
{
|
||||
var defaultLanguage = "eng";
|
||||
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
return defaultLanguage;
|
||||
}
|
||||
|
||||
var fileNameNoExt = Path.GetFileNameWithoutExtension(fileName);
|
||||
var split = fileNameNoExt.Split('.', '_', '_');
|
||||
var last = split.LastOrDefault();
|
||||
|
||||
if (last == null)
|
||||
{
|
||||
return defaultLanguage;
|
||||
}
|
||||
|
||||
if (last.Length == 3)
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
if (last.Length == 2)
|
||||
{
|
||||
var threeLetterCode = Iso639Dash2LanguageCode.GetThreeLetterCodeFromTwoLetterCode(last);
|
||||
if (threeLetterCode.Length == 3)
|
||||
{
|
||||
return threeLetterCode;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultLanguage;
|
||||
}
|
||||
|
||||
private string GetKnownFileNameOrConvertToSrtOrUtf8(string fileName, Subtitle subtitle)
|
||||
{
|
||||
SubtitleFormat targetFormat = new SubRip();
|
||||
@ -390,6 +441,13 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
VideoFileName = saveDialog.FileName;
|
||||
}
|
||||
|
||||
var isMp4 = VideoFileName.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase);
|
||||
if (isMp4 && _softSubs.Any(p => p.SubtitleFormat == "S_HDMV/PGS"))
|
||||
{
|
||||
MessageBox.Show("Cannot embed S_HDMV/PGS in MP4");
|
||||
return;
|
||||
}
|
||||
|
||||
if (File.Exists(VideoFileName))
|
||||
{
|
||||
try
|
||||
@ -550,6 +608,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
return VideoPreviewGenerator.GenerateSoftCodedVideoFile(
|
||||
inputVideoFileName,
|
||||
_softSubs,
|
||||
_tracksToDelete,
|
||||
outputVideoFileName,
|
||||
OutputHandler);
|
||||
}
|
||||
@ -756,6 +815,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
foreach (var index in list.OrderByDescending(p => p))
|
||||
{
|
||||
_tracksToDelete.Add(_softSubs[index]);
|
||||
_softSubs.RemoveAt(index);
|
||||
listViewSubtitles.Items.RemoveAt(index);
|
||||
}
|
||||
@ -780,6 +840,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
private void buttonClear_Click(object sender, EventArgs e)
|
||||
{
|
||||
listViewSubtitles.Items.Clear();
|
||||
_tracksToDelete.AddRange(_softSubs);
|
||||
_softSubs.Clear();
|
||||
labelSubtitles.Text = string.Format(LanguageSettings.Current.GenerateVideoWithEmbeddedSubs.SubtitlesX, listViewSubtitles.Items.Count);
|
||||
}
|
||||
|
@ -2716,6 +2716,9 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
case "GenerateVideoWithEmbeddedSubs/XGeneratedWithEmbeddedSubs":
|
||||
language.GenerateVideoWithEmbeddedSubs.XGeneratedWithEmbeddedSubs = reader.Value;
|
||||
break;
|
||||
case "GenerateVideoWithEmbeddedSubs/DeleteInputVideo":
|
||||
language.GenerateVideoWithEmbeddedSubs.DeleteInputVideo = reader.Value;
|
||||
break;
|
||||
case "GetDictionaries/Title":
|
||||
language.GetDictionaries.Title = reader.Value;
|
||||
break;
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
using Nikse.SubtitleEdit.Core.SubtitleFormats;
|
||||
using Nikse.SubtitleEdit.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -9,6 +8,7 @@ using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Nikse.SubtitleEdit.Core.ContainerFormats.Matroska;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic
|
||||
{
|
||||
@ -355,18 +355,116 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
return ffmpegLocation;
|
||||
}
|
||||
|
||||
public static Process GenerateSoftCodedVideoFile(string inputVideoFileName, List<VideoPreviewGeneratorSub> softSubs, string outputVideoFileName, DataReceivedEventHandler outputHandler)
|
||||
public static Process GenerateSoftCodedVideoFile(string inputVideoFileName, List<VideoPreviewGeneratorSub> softSubs, List<VideoPreviewGeneratorSub> softSubsToDelete, string outputVideoFileName, DataReceivedEventHandler outputHandler)
|
||||
{
|
||||
var isMp4 = outputVideoFileName.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase);
|
||||
if (isMp4)
|
||||
{
|
||||
return GenerateSoftCodedVideoFileMp4(inputVideoFileName, softSubs, outputVideoFileName, outputHandler);
|
||||
}
|
||||
|
||||
var subsInput = string.Empty;
|
||||
var subsMeta = string.Empty;
|
||||
var map = "-map 0";
|
||||
|
||||
foreach (var trackToDelete in softSubsToDelete)
|
||||
{
|
||||
if (!trackToDelete.IsNew && trackToDelete.Tag is MatroskaTrackInfo trackInfo)
|
||||
{
|
||||
map += $" -map -0:{trackInfo.TrackNumber - 1}";
|
||||
}
|
||||
}
|
||||
|
||||
var count = 1;
|
||||
var number = 0;
|
||||
foreach (var softSub in softSubs.Where(p => p.IsNew))
|
||||
{
|
||||
map += $" -map {count}";
|
||||
|
||||
subsInput += $" -i \"{softSub.FileName}\"";
|
||||
|
||||
if (!string.IsNullOrEmpty(softSub.Language))
|
||||
{
|
||||
var lang = string.IsNullOrEmpty(softSub.Language) ? string.Empty : softSub.Language.ToLowerInvariant();
|
||||
var threeLetterCode = Iso639Dash2LanguageCode.GetThreeLetterCodeFromTwoLetterCode(lang);
|
||||
if (lang.Length == 3)
|
||||
{
|
||||
threeLetterCode = lang;
|
||||
}
|
||||
else if (lang.IndexOf('-') == 2)
|
||||
{
|
||||
threeLetterCode = Iso639Dash2LanguageCode.GetThreeLetterCodeFromTwoLetterCode(lang.Substring(0, 2));
|
||||
}
|
||||
|
||||
var languageName = Iso639Dash2LanguageCode.List.FirstOrDefault(p => p.ThreeLetterCode == threeLetterCode)?.EnglishName;
|
||||
if (languageName == null)
|
||||
{
|
||||
languageName = Iso639Dash2LanguageCode.List.FirstOrDefault(p => p.TwoLetterCode == lang || p.EnglishName.ToLowerInvariant() == lang)?.EnglishName;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(threeLetterCode) && !string.IsNullOrEmpty(languageName))
|
||||
{
|
||||
subsMeta += $" -metadata:s:s:{number} language=\"{threeLetterCode}\"";
|
||||
subsMeta += $" -metadata:s:s:{number} title=\"{languageName}\"";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(softSub.Language))
|
||||
{
|
||||
subsMeta += $" -metadata:s:s:{number} language=\"{softSub.Language}\"";
|
||||
subsMeta += $" -metadata:s:s:{number} title=\"{softSub.Language}\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (softSub.IsDefault)
|
||||
{
|
||||
subsMeta += $" -disposition:s:s:{number} default";
|
||||
}
|
||||
|
||||
if (softSub.IsForced)
|
||||
{
|
||||
subsMeta += $" -disposition:s:s:{number} forced";
|
||||
subsMeta += $" -metadata:s:s:{number} forced=1";
|
||||
}
|
||||
|
||||
count++;
|
||||
number++;
|
||||
}
|
||||
|
||||
subsInput = " " + subsInput.Trim();
|
||||
if (subsInput.Trim().Length == 0)
|
||||
{
|
||||
subsInput = string.Empty;
|
||||
}
|
||||
|
||||
subsMeta = " " + subsMeta.Trim();
|
||||
if (subsMeta.Trim().Length == 0)
|
||||
{
|
||||
subsMeta = string.Empty;
|
||||
}
|
||||
|
||||
var arguments = $"-i \"{inputVideoFileName}\" {subsInput.Trim()} {map.Trim()} -c copy {subsMeta.Trim()} \"{outputVideoFileName}\"".TrimStart();
|
||||
var processMakeVideo = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = GetFfmpegLocation(),
|
||||
Arguments = arguments,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
}
|
||||
};
|
||||
|
||||
processMakeVideo.StartInfo.Arguments = processMakeVideo.StartInfo.Arguments.Trim();
|
||||
SetupDataReceiveHandler(outputHandler, processMakeVideo);
|
||||
return processMakeVideo;
|
||||
}
|
||||
|
||||
private static Process GenerateSoftCodedVideoFileMp4(string inputVideoFileName, List<VideoPreviewGeneratorSub> softSubs, string outputVideoFileName, DataReceivedEventHandler outputHandler)
|
||||
{
|
||||
var subsInput = string.Empty;
|
||||
var subsMap = string.Empty;
|
||||
var subsMeta = string.Empty;
|
||||
var subsFormat = string.Empty;
|
||||
|
||||
var ffmpegInfo = FfmpegMediaInfo.Parse(inputVideoFileName);
|
||||
var audioTrackCount = ffmpegInfo.Tracks.Count(p => p.TrackType == FfmpegTrackType.Audio);
|
||||
|
||||
var isMp4 = outputVideoFileName.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var count = 1;
|
||||
var number = 0;
|
||||
foreach (var softSub in softSubs)
|
||||
@ -416,31 +514,7 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
subsMeta += $" -metadata:s:s:{number} forced=1";
|
||||
}
|
||||
|
||||
if (isMp4)
|
||||
{
|
||||
subsFormat = " -c:s mov_text";
|
||||
}
|
||||
else if (softSub.SubtitleFormat == null && softSub.Format == "Blu-ray sup")
|
||||
{
|
||||
subsFormat += $" -c:s:s:{number} copy"; // should be "pgs" or "pgssub" or ?
|
||||
}
|
||||
else if (softSub.SubtitleFormat?.GetType() == typeof(SubRip))
|
||||
{
|
||||
subsFormat += $" -c:s:s:{number} srt";
|
||||
}
|
||||
else if (softSub.SubtitleFormat?.GetType() == typeof(AdvancedSubStationAlpha))
|
||||
{
|
||||
subsFormat += $" -c:s:s:{number} ass";
|
||||
}
|
||||
else if (softSub.SubtitleFormat?.GetType() == typeof(SubStationAlpha))
|
||||
{
|
||||
subsFormat += $" -c:s:s:{number} ssa";
|
||||
}
|
||||
else if (softSub.SubtitleFormat?.GetType() == typeof(WebVTT) ||
|
||||
softSub.SubtitleFormat?.GetType() == typeof(WebVTTFileWithLineNumber))
|
||||
{
|
||||
subsFormat += $" -c:s:s:{number} webvtt";
|
||||
}
|
||||
subsFormat = " -c:s mov_text";
|
||||
|
||||
count++;
|
||||
number++;
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
using Nikse.SubtitleEdit.Core.SubtitleFormats;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic
|
||||
{
|
||||
@ -9,7 +8,7 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
public bool IsNew { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public Subtitle Subtitle { get; set; }
|
||||
public SubtitleFormat SubtitleFormat { get; set; }
|
||||
public string SubtitleFormat { get; set; }
|
||||
public string Format { get; set; }
|
||||
public string Language { get; set; }
|
||||
public bool IsForced { get; set; }
|
||||
|
Loading…
Reference in New Issue
Block a user