added Audio Add Track node

This commit is contained in:
reven
2022-01-31 12:08:04 +13:00
parent 05eff9b237
commit 5544960179
4 changed files with 241 additions and 1 deletions

View File

@@ -0,0 +1,46 @@
#if(DEBUG)
namespace VideoNodes.Tests
{
using FileFlows.VideoNodes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
[TestClass]
public class AudioAddTrackTests
{
[TestMethod]
public void AudioAddTrackTests_Mono_First()
{
const string file = @"D:\videos\unprocessed\The Witcher - S02E05 - Turn Your Back.mkv";
var logger = new TestLogger();
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", logger);
var vii = vi.Read(file);
const string ffmpeg = @"C:\utils\ffmpeg\ffmpeg.exe";
AudioAddTrack node = new();
var args = new FileFlows.Plugin.NodeParameters(file, logger, false, string.Empty);
args.GetToolPathActual = (string tool) => ffmpeg;
args.TempPath = @"D:\videos\temp";
new VideoFile().Execute(args);
node.Bitrate = 128;
node.Channels = 2;
node.Index = 2;
node.Codec = "aac";
int output = node.Execute(args);
string log = logger.ToString();
Assert.AreEqual(1, output);
}
}
}
#endif

View File

@@ -1,6 +1,21 @@
{
"Flow":{
"Parts": {
"AudioAddTrack": {
"Outputs": {
"1": "Audio track adde and saved to temporary file"
},
"Description": "Adds a new audio track to ta video file, all other audio tracks will remain. This will use the first audio track of the file as the source audio track to convert.",
"Fields": {
"Index": "Index",
"Index-Help": "The index where to insert the new audio track. 1 based, so to insert the new audio track as the first track set this to 1.",
"Channels": "Channels",
"Channels-Help": "The number of channels to convert this audio track to.",
"Bitrate": "Bitrate",
"Bitrate-Help": "Bitrate of the new audio track"
}
},
"AudioAdjustVolume": {
"Outputs": {
"1": "Audio tracks volume was adjusted and saved to temporary file",

View File

@@ -0,0 +1,179 @@
namespace FileFlows.VideoNodes
{
using FileFlows.Plugin;
using FileFlows.Plugin.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
public class AudioAddTrack: EncodingNode
{
public override int Outputs => 1;
public override string Icon => "fas fa-volume-down";
[NumberInt(1)]
[Range(1, 100)]
public int Index { get; set; }
[Select(nameof(CodecOptions), 1)]
public string Codec { get; set; }
private static List<ListOption> _CodecOptions;
public static List<ListOption> CodecOptions
{
get
{
if (_CodecOptions == null)
{
_CodecOptions = new List<ListOption>
{
new ListOption { Label = "AAC", Value = "aac"},
new ListOption { Label = "AC3", Value = "ac3"},
new ListOption { Label = "EAC3", Value = "eac3" },
new ListOption { Label = "MP3", Value = "mp3"},
};
}
return _CodecOptions;
}
}
[Select(nameof(ChannelsOptions), 2)]
public float Channels { get; set; }
private static List<ListOption> _ChannelsOptions;
public static List<ListOption> ChannelsOptions
{
get
{
if (_ChannelsOptions == null)
{
_ChannelsOptions = new List<ListOption>
{
new ListOption { Label = "Same as source", Value = 0},
new ListOption { Label = "Mono", Value = 1f},
new ListOption { Label = "Stereo", Value = 2f}
};
}
return _ChannelsOptions;
}
}
[Select(nameof(BitrateOptions), 3)]
public int Bitrate { get; set; }
private static List<ListOption> _BitrateOptions;
public static List<ListOption> BitrateOptions
{
get
{
if (_BitrateOptions == null)
{
_BitrateOptions = new List<ListOption>
{
new ListOption { Label = "64 Kbps", Value = 64},
new ListOption { Label = "96 Kbps", Value = 96},
new ListOption { Label = "128 Kbps", Value = 128},
new ListOption { Label = "160 Kbps", Value = 160},
new ListOption { Label = "192 Kbps", Value = 192},
new ListOption { Label = "224 Kbps", Value = 224},
new ListOption { Label = "256 Kbps", Value = 256},
new ListOption { Label = "288 Kbps", Value = 288},
new ListOption { Label = "320 Kbps", Value = 320},
};
}
return _BitrateOptions;
}
}
public override int Execute(NodeParameters args)
{
try
{
VideoInfo videoInfo = GetVideoInfo(args);
if (videoInfo == null)
return -1;
string ffmpegExe = GetFFMpegExe(args);
if (string.IsNullOrEmpty(ffmpegExe))
return -1;
List<string> ffArgs = new List<string>
{
"-c", "copy",
"-map", "0:v",
};
bool added = false;
int audioIndex = 0;
for(int i = 0; i < videoInfo.AudioStreams.Count; i++)
{
if((i + 1) == Index)
{
ffArgs.AddRange(GetNewAudioTrackParameters(videoInfo, audioIndex));
added = true;
++audioIndex;
}
ffArgs.AddRange(new[]
{
"-map", videoInfo.AudioStreams[i].IndexString,
"-c:a:" + audioIndex, "copy"
});
++audioIndex;
}
if(added == false) // incase the index is greater than the number of tracks this file has
ffArgs.AddRange(GetNewAudioTrackParameters(videoInfo, audioIndex));
if (videoInfo.SubtitleStreams?.Any() == true)
ffArgs.AddRange(new[] { "-map", "0:s" });
if (Index < 2)
{
// this makes the first audio track now the default track
ffArgs.AddRange(new[] { "-disposition:a:0", "default" });
}
string extension = new FileInfo(args.WorkingFile).Extension;
if(extension.StartsWith("."))
extension = extension.Substring(1);
if (Encode(args, ffmpegExe, ffArgs, extension) == false)
return -1;
return 1;
}
catch (Exception ex)
{
args.Logger?.ELog("Failed processing VideoFile: " + ex.Message);
return -1;
}
}
private string[] GetNewAudioTrackParameters(VideoInfo videoInfo, int index)
{
if (Channels == 0)
{
// same as source
return new[]
{
"-map", videoInfo.AudioStreams[0].IndexString,
"-c:a:" + index, Codec,
"-b:a:" + index, Bitrate + "k"
};
}
else
{
return new[]
{
"-map", videoInfo.AudioStreams[0].IndexString,
"-c:a:" + index, Codec,
"-ac", Channels.ToString(),
"-b:a:" + index, Bitrate + "k"
};
}
}
}
}

View File

@@ -142,6 +142,6 @@
args.Logger?.ELog("Failed processing VideoFile: " + ex.Message);
return -1;
}
}
}
}
}