Fixed audio compatibility check, improved lossless audio transfer

This commit is contained in:
N00MKRAD
2021-03-24 14:40:01 +01:00
parent b0e5cbdf1c
commit 115cff131e
3 changed files with 49 additions and 21 deletions

View File

@@ -97,7 +97,10 @@ namespace Flowframes.Media
public static bool ContainerSupportsAllAudioFormats (Interpolate.OutMode outMode, List<string> codecs)
{
foreach(string format in codecs)
if(codecs.Count < 1)
Logger.Log($"Warning: ContainerSupportsAllAudioFormats() was called, but codec list has {codecs.Count} entries.", true, false, "ffmpeg");
foreach (string format in codecs)
{
if (!ContainerSupportsAudioFormat(outMode, format))
return false;
@@ -108,7 +111,8 @@ namespace Flowframes.Media
public static bool ContainerSupportsAudioFormat (Interpolate.OutMode outMode, string format)
{
format = format.Remove(".");
string alias = GetAudioExt(format);
Logger.Log($"Checking if {outMode} supports audio format '{format}' (alias {alias})", true, false, "ffmpeg");
string[] formatsMp4 = new string[] { "m4a", "ac3", "dts" };
string[] formatsMkv = new string[] { "m4a", "ac3", "dts", "ogg", "mp2", "wav" };
@@ -118,11 +122,11 @@ namespace Flowframes.Media
switch (outMode)
{
case Interpolate.OutMode.VidMp4: return formatsMp4.Contains(format);
case Interpolate.OutMode.VidMkv: return formatsMkv.Contains(format);
case Interpolate.OutMode.VidWebm: return formatsWebm.Contains(format);
case Interpolate.OutMode.VidProRes: return formatsProres.Contains(format);
case Interpolate.OutMode.VidAvi: return formatsAvi.Contains(format);
case Interpolate.OutMode.VidMp4: return formatsMp4.Contains(alias);
case Interpolate.OutMode.VidMkv: return formatsMkv.Contains(alias);
case Interpolate.OutMode.VidWebm: return formatsWebm.Contains(alias);
case Interpolate.OutMode.VidProRes: return formatsProres.Contains(alias);
case Interpolate.OutMode.VidAvi: return formatsAvi.Contains(alias);
}
return false;
@@ -147,17 +151,29 @@ namespace Flowframes.Media
public static string GetAudioExt(string videoFile, int streamIndex = -1)
{
switch (FfmpegCommands.GetAudioCodec(videoFile, streamIndex))
return GetAudioExt(FfmpegCommands.GetAudioCodec(videoFile, streamIndex));
}
public static string GetAudioExt (string codec)
{
if (codec.StartsWith("pcm_"))
return "wav";
switch (codec)
{
case "vorbis": return "ogg";
case "opus": return "ogg";
case "mp2": return "mp2";
case "mp3": return "mp3";
case "aac": return "m4a";
case "ac3": return "ac3";
case "eac3": return "ac3";
case "dts": return "dts";
default: return "wav";
case "alac": return "wav";
case "flac": return "wav";
}
return "unsupported";
}
public static string GetAudioFallbackArgs (Interpolate.OutMode outMode)

View File

@@ -29,7 +29,7 @@ namespace Flowframes.Media
foreach (AudioTrack track in audioTracks)
{
if (Interpolate.canceled) break;
if (I.canceled) break;
string audioExt = Utils.GetAudioExt(inputFile, track.streamIndex);
string outPath = Path.Combine(outFolder, $"{track.streamIndex}_{track.metadata}_audio.{audioExt}");
@@ -37,15 +37,15 @@ namespace Flowframes.Media
string args = $"{trim[0]} -i {inputFile.Wrap()} {trim[1]} -map 0:{track.streamIndex} -vn -c:a copy {outPath.Wrap()}";
await RunFfmpeg(args, LogMode.Hidden, "panic");
if (File.Exists(outPath) && IOUtils.GetFilesize(outPath) < 512)
if (IOUtils.GetFilesize(outPath) < 512)
{
Logger.Log($"Failed to extract audio stream #{track.streamIndex} losslessly! Trying to re-encode.");
// Logger.Log($"Failed to extract audio stream #{track.streamIndex} losslessly! Trying to re-encode.");
File.Delete(outPath);
outPath = Path.ChangeExtension(outPath, Utils.GetAudioExtForContainer(Path.GetExtension(inputFile)));
args = $"{trim[0]} -i {inputFile.Wrap()} {trim[1]} -vn {Utils.GetAudioFallbackArgs(Interpolate.current.outMode)} {outPath.Wrap()}";
args = $"{trim[0]} -i {inputFile.Wrap()} {trim[1]} -vn {Utils.GetAudioFallbackArgs(I.current.outMode)} {outPath.Wrap()}";
await RunFfmpeg(args, LogMode.Hidden, "panic", TaskType.ExtractOther, true);
if (File.Exists(outPath) && IOUtils.GetFilesize(outPath) < 512)
if (IOUtils.GetFilesize(outPath) < 512)
{
Logger.Log($"Failed to extract audio stream #{track.streamIndex}, even with re-encoding. Will be missing from output.");
IOUtils.TryDeleteIfExists(outPath);
@@ -73,7 +73,7 @@ namespace Flowframes.Media
string line = outputLines[i];
if (!line.Contains(" Audio: ")) continue;
int streamIndex = line.Remove("Stream #0:").Split(':')[0].GetInt();
int streamIndex = line.Remove("Stream #0:").Split(':')[0].Split('[')[0].GetInt();
string meta = "";
string codec = "";
@@ -171,6 +171,7 @@ namespace Flowframes.Media
#endregion
#region Mux From Input
public static async Task MergeStreamsFromInput (string inputVideo, string interpVideo, string tempFolder)
{
if (!File.Exists(inputVideo) && !I.current.inputIsFrames)
@@ -188,9 +189,12 @@ namespace Flowframes.Media
string subArgs = "-c:s " + Utils.GetSubCodecForContainer(containerExt);
bool audioCompat = Utils.ContainerSupportsAllAudioFormats(I.current.outMode, GetAudioCodecs(interpVideo));
bool audioCompat = Utils.ContainerSupportsAllAudioFormats(I.current.outMode, GetAudioCodecs(inputVideo));
string audioArgs = audioCompat ? "" : Utils.GetAudioFallbackArgs(I.current.outMode);
if (!audioCompat)
Logger.Log("Warning: Input audio format(s) not fully supported in output container - Will re-encode.", true, false, "ffmpeg");
bool enableAudio = Config.GetBool("keepAudio");
bool enableSubs = Config.GetBool("keepSubs");
@@ -232,6 +236,10 @@ namespace Flowframes.Media
}
}
#endregion
#region Mux From Extracted Streams
public static async Task MergeAudioAndSubs(string interpVideo, string tempFolder) // https://superuser.com/a/277667
{
string containerExt = Path.GetExtension(interpVideo);
@@ -288,17 +296,17 @@ namespace Flowframes.Media
inputIndex++;
}
bool allAudioCodecsSupported = true;
bool audioCompat = true;
foreach (string audioTrack in audioTracks)
if (!Utils.ContainerSupportsAudioFormat(I.current.outMode, Path.GetExtension(audioTrack)))
allAudioCodecsSupported = false;
audioCompat = false;
if(!allAudioCodecsSupported)
Logger.Log("Warning: Input audio format(s) not fully supported in output container. Audio transfer will not be lossless.", false, false, "ffmpeg");
if(!audioCompat)
Logger.Log("Warning: Input audio format(s) not fully supported in output container - Will re-encode.", true, false, "ffmpeg");
string subArgs = "-c:s " + Utils.GetSubCodecForContainer(containerExt);
string audioArgs = allAudioCodecsSupported ? "-c:a copy" : Utils.GetAudioFallbackArgs(I.current.outMode);
string audioArgs = audioCompat ? "-c:a copy" : Utils.GetAudioFallbackArgs(I.current.outMode);
string args = $" -i {inName} {trackInputArgs} -map 0:v {trackMapArgs} -c:v copy {audioArgs} {subArgs} {trackMetaArgs} {outName}";
@@ -336,5 +344,7 @@ namespace Flowframes.Media
File.Move(tempPath, interpVideo);
}
}
#endregion
}
}

View File

@@ -197,6 +197,7 @@ namespace Flowframes
public static string GetAudioCodec(string path, int streamIndex = -1)
{
Logger.Log($"GetAudioCodec('{Path.GetFileName(path)}', {streamIndex})", true, false, "ffmpeg");
string stream = (streamIndex < 0) ? "a" : $"{streamIndex}";
string args = $"-v panic -show_streams -select_streams {stream} -show_entries stream=codec_name {path.Wrap()}";
string info = GetFfprobeOutput(args);
@@ -212,6 +213,7 @@ namespace Flowframes
public static List<string> GetAudioCodecs(string path, int streamIndex = -1)
{
Logger.Log($"GetAudioCodecs('{Path.GetFileName(path)}', {streamIndex})", true, false, "ffmpeg");
List<string> codecNames = new List<string>();
string args = $"-loglevel panic -select_streams a -show_entries stream=codec_name {path.Wrap()}";
string info = GetFfprobeOutput(args);