mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2025-12-31 07:39:29 -06:00
added comskip remove ads node
This commit is contained in:
@@ -26,10 +26,13 @@ namespace FileFlows.VideoNodes
|
||||
this.Logger = logger;
|
||||
}
|
||||
|
||||
public bool Encode(string input, string output, string arguments)
|
||||
public bool Encode(string input, string output, string arguments, bool dontAddInputFile = false)
|
||||
{
|
||||
// -y means it will overwrite a file if output already exists
|
||||
arguments = $"-i \"{input}\" -y {arguments} \"{output}\"";
|
||||
if(dontAddInputFile == false)
|
||||
arguments = $"-i \"{input}\" -y {arguments} \"{output}\"";
|
||||
else
|
||||
arguments = $"{arguments} \"{output}\"";
|
||||
|
||||
Logger.ILog(new string('=', ("FFMpeg.Arguments: " + arguments).Length));
|
||||
Logger.ILog("FFMpeg.Arguments: " + arguments);
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace VideoNodes.Tests
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\Bourne.mkv";
|
||||
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", new TestLogger());
|
||||
vi.Read(@"D:\videos\unprocessed\Bourne.mkv");
|
||||
var vii = vi.Read(@"D:\videos\unprocessed\Masters of the Universe (1987) Bluray-1080p.mkv.skip");
|
||||
|
||||
SubtitleRemover remover = new SubtitleRemover();
|
||||
remover.SubtitlesToRemove = new List<string>
|
||||
@@ -267,6 +267,29 @@ namespace VideoNodes.Tests
|
||||
Assert.AreEqual("ac3", reordered[7].Codec);
|
||||
Assert.AreEqual("fre", reordered[7].Language);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void ComskipTest()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\The IT Crowd - 2x04 - The Dinner Party - No English.mkv";
|
||||
const string ffmpeg = @"C:\utils\ffmpeg\ffmpeg.exe";
|
||||
var args = new FileFlows.Plugin.NodeParameters(file, new TestLogger(), false, string.Empty);
|
||||
|
||||
args.GetToolPath = (string tool) => @"C:\utils\ffmpeg\ffmpeg.exe";
|
||||
args.TempPath = @"D:\videos\temp";
|
||||
|
||||
|
||||
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", new TestLogger());
|
||||
var vii = vi.Read(file);
|
||||
args.SetParameter("VideoInfo", vii);
|
||||
//args.Process = new FileFlows.Plugin.ProcessHelper(args.Logger);
|
||||
|
||||
var node = new ComskipRemoveAds();
|
||||
int output = node.Execute(args);
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -48,6 +48,13 @@
|
||||
"Language-Help": "The ISO 639-2 language code to use. \nhttps://en.wikipedia.org/wiki/List_of_ISO_639-2_codes"
|
||||
}
|
||||
},
|
||||
"ComskipRemoveAds": {
|
||||
"Description": "Uses a comskip EDL file and will remove commericals using that file.",
|
||||
"Outputs": {
|
||||
"1": "Commericals removed, saved to temporary file",
|
||||
"2": "No commericals detected"
|
||||
}
|
||||
},
|
||||
"VideoFile": {
|
||||
"Description": "An input video file that has had its VideoInformation read and can be processed",
|
||||
"Outputs": {
|
||||
|
||||
128
VideoNodes/VideoNodes/ComskipRemoveAds.cs
Normal file
128
VideoNodes/VideoNodes/ComskipRemoveAds.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
namespace FileFlows.VideoNodes
|
||||
{
|
||||
using FileFlows.Plugin;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
public class ComskipRemoveAds: EncodingNode
|
||||
{
|
||||
public override int Outputs => 2;
|
||||
|
||||
public override int Execute(NodeParameters args)
|
||||
{
|
||||
string ffmpegExe = GetFFMpegExe(args);
|
||||
if (string.IsNullOrEmpty(ffmpegExe))
|
||||
return -1;
|
||||
VideoInfo videoInfo = GetVideoInfo(args);
|
||||
if (videoInfo == null)
|
||||
return -1;
|
||||
float totalTime = (float)videoInfo.VideoStreams[0].Duration.TotalSeconds;
|
||||
|
||||
|
||||
string edlFile = args.WorkingFile.Substring(0, args.WorkingFile.LastIndexOf(".") + 1) + "edl";
|
||||
if(File.Exists(edlFile) == false)
|
||||
edlFile = args.WorkingFile.Substring(0, args.WorkingFile.LastIndexOf(".") + 1) + "edl";
|
||||
if (File.Exists(edlFile) == false)
|
||||
{
|
||||
args.Logger?.ILog("No EDL file found for file");
|
||||
return 2;
|
||||
}
|
||||
|
||||
string text = File.ReadAllText(edlFile) ?? string.Empty;
|
||||
float last = -1;
|
||||
List<BreakPoint> breakPoints = new List<BreakPoint>();
|
||||
foreach(string line in text.Split(new string[] { "\r\n", "\n", "\r"}, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
// 93526.47 93650.13 0
|
||||
string[] parts = line.Split(" ");
|
||||
if (parts.Length < 2)
|
||||
continue;
|
||||
float start = 0;
|
||||
float end = 0;
|
||||
if (float.TryParse(parts[0], out start) == false || float.TryParse(parts[1], out end) == false)
|
||||
continue;
|
||||
|
||||
if (start < last)
|
||||
continue;
|
||||
|
||||
BreakPoint bp = new BreakPoint();
|
||||
bp.Start = start;
|
||||
bp.End = end;
|
||||
breakPoints.Add(bp);
|
||||
}
|
||||
|
||||
if(breakPoints.Any() == false)
|
||||
{
|
||||
args.Logger?.ILog("No break points detected in file");
|
||||
return 2;
|
||||
}
|
||||
|
||||
List<string> segments = new List<string>();
|
||||
|
||||
float segStart = 0;
|
||||
string extension = args.WorkingFile.Substring(args.WorkingFile.LastIndexOf(".") + 1);
|
||||
string segmentPrefix = Path.Combine(args.TempPath, Guid.NewGuid().ToString())+"_";
|
||||
int count = 0;
|
||||
foreach (BreakPoint bp in breakPoints)
|
||||
{
|
||||
if(EncodeSegment(segStart, bp.Duration) == false)
|
||||
{
|
||||
args.Logger?.ELog("Failed to create segment: " + count);
|
||||
return 2;
|
||||
}
|
||||
segStart = bp.End;
|
||||
}
|
||||
// add the end
|
||||
if (EncodeSegment(segStart, totalTime - segStart) == false)
|
||||
{
|
||||
args.Logger?.ELog("Failed to create segment: " + count);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
// stitch file back together
|
||||
string concatList = segmentPrefix + "concatlist.txt";
|
||||
File.WriteAllLines(concatList, segments.Select(x => $"file '{x}'"));
|
||||
|
||||
bool concatResult = Encode(args, ffmpegExe, $"-f concat -safe 0 -i \"{concatList}\" -c copy", dontAddInputFile: true, extension: extension);
|
||||
|
||||
foreach(string segment in segments.Union(new[] { concatList }))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(segment);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
if (concatResult)
|
||||
return 1;
|
||||
args.Logger?.ELog("Failed to stitch file back together");
|
||||
return 2;
|
||||
|
||||
bool EncodeSegment(float start, float duration)
|
||||
{
|
||||
string segment = segmentPrefix + (++count).ToString("D2") + "." + extension;
|
||||
if (Encode(args, ffmpegExe, $"-ss {start} -t {duration} -c copy", outputFile: segment, updateWorkingFile: false))
|
||||
{
|
||||
segments.Add(segment);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class BreakPoint
|
||||
{
|
||||
public float Start { get; set; }
|
||||
public float End { get; set; }
|
||||
|
||||
public float Duration => End - Start;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ namespace FileFlows.VideoNodes
|
||||
|
||||
private FFMpegEncoder Encoder;
|
||||
|
||||
protected bool Encode(NodeParameters args, string ffmpegExe, string ffmpegParameters, string extension = "mkv", string outputFile = "")
|
||||
protected bool Encode(NodeParameters args, string ffmpegExe, string ffmpegParameters, string extension = "mkv", string outputFile = "", bool updateWorkingFile = true, bool dontAddInputFile = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(extension))
|
||||
extension = "mkv";
|
||||
@@ -30,9 +30,9 @@ namespace FileFlows.VideoNodes
|
||||
if (string.IsNullOrEmpty(outputFile))
|
||||
outputFile = Path.Combine(args.TempPath, Guid.NewGuid().ToString() + "." + extension);
|
||||
|
||||
bool success = Encoder.Encode(args.WorkingFile, outputFile, ffmpegParameters);
|
||||
bool success = Encoder.Encode(args.WorkingFile, outputFile, ffmpegParameters, dontAddInputFile: dontAddInputFile);
|
||||
args.Logger.ILog("Encoding succesful: " + success);
|
||||
if (success)
|
||||
if (success && updateWorkingFile)
|
||||
{
|
||||
args.SetWorkingFile(outputFile);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user