mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2025-12-21 09:30:03 -06:00
added option to copy/move nodes to also move additional files
This commit is contained in:
Binary file not shown.
@@ -32,7 +32,11 @@
|
||||
"DestinationFile": "Destination File",
|
||||
"DestinationFile-Help": "The filename to copy the file to. If empty, the original filename will be used",
|
||||
"CopyFolder": "Copy Folder",
|
||||
"CopyFolder-Help": "If the relative library folder structure should be copied too"
|
||||
"CopyFolder-Help": "If the relative library folder structure should be copied too",
|
||||
"AdditionalFiles": "Additional Files",
|
||||
"AdditionalFiles-Help": "Additional files to copy from the directory to the new directory.\nEach value can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn''t support regular expressions.",
|
||||
"AdditionalFilesFromOriginal": "Original Directory",
|
||||
"AdditionalFilesFromOriginal-Help": "If the additional files should be copied from the working directory or from the original directory. Turn on for original directory."
|
||||
}
|
||||
},
|
||||
"DeleteSourceDirectory": {
|
||||
@@ -180,7 +184,11 @@
|
||||
"MoveFolder": "Copy Folder",
|
||||
"MoveFolder-Help": "If the relative library folder structure should be copied too",
|
||||
"DeleteOriginal": "Delete Original",
|
||||
"DeleteOriginal-Help": "If the original file should be deleted, this will only happen if the working file is different to the original file"
|
||||
"DeleteOriginal-Help": "If the original file should be deleted, this will only happen if the working file is different to the original file",
|
||||
"AdditionalFiles": "Additional Files",
|
||||
"AdditionalFiles-Help": "Additional files to move from the directory to the new directory.\nEach value can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn''t support regular expressions.",
|
||||
"AdditionalFilesFromOriginal": "Original Directory",
|
||||
"AdditionalFilesFromOriginal-Help": "If the additional files should be moved from the working directory or from the original directory. Turn on for original directory."
|
||||
}
|
||||
},
|
||||
"OriginalFile": {
|
||||
|
||||
@@ -31,6 +31,12 @@ namespace FileFlows.BasicNodes.File
|
||||
[Boolean(3)]
|
||||
public bool CopyFolder { get; set; }
|
||||
|
||||
[StringArray(4)]
|
||||
public string[] AdditionalFiles { get; set; }
|
||||
|
||||
[Boolean(5)]
|
||||
public bool AdditionalFilesFromOriginal { get; set; }
|
||||
|
||||
private bool Canceled;
|
||||
|
||||
public override Task Cancel()
|
||||
@@ -118,12 +124,39 @@ namespace FileFlows.BasicNodes.File
|
||||
args?.Logger?.ELog("Action was canceled.");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
args?.SetWorkingFile(dest);
|
||||
|
||||
return base.Execute(args!);
|
||||
var srcDir = AdditionalFilesFromOriginal ? new FileInfo(args.FileName).DirectoryName : new FileInfo(args.WorkingFile).DirectoryName;
|
||||
|
||||
if (AdditionalFiles?.Any() == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var diSrc = new DirectoryInfo(srcDir);
|
||||
foreach (var additional in AdditionalFiles)
|
||||
{
|
||||
foreach (var addFile in diSrc.GetFiles(additional))
|
||||
{
|
||||
try
|
||||
{
|
||||
string addFileDest = Path.Combine(destDir, addFile.Name);
|
||||
System.IO.File.Copy(addFile.FullName, addFileDest, true);
|
||||
args.Logger?.ILog("Copyied file: \"" + addFile.FullName + "\" to \"" + addFileDest + "\"");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
args.Logger?.ILog("Failed copying file: \"" + addFile.FullName + "\": " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
args.Logger.WLog("Error copying additinoal files: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
args?.SetWorkingFile(dest);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,12 @@ namespace FileFlows.BasicNodes.File
|
||||
[Boolean(4)]
|
||||
public bool DeleteOriginal { get; set; }
|
||||
|
||||
[StringArray(5)]
|
||||
public string[] AdditionalFiles { get; set; }
|
||||
|
||||
[Boolean(6)]
|
||||
public bool AdditionalFilesFromOriginal { get; set; }
|
||||
|
||||
public override int Execute(NodeParameters args)
|
||||
{
|
||||
string dest = args.ReplaceVariables(DestinationPath, true);
|
||||
@@ -68,9 +74,40 @@ namespace FileFlows.BasicNodes.File
|
||||
var destDir = fiDest.DirectoryName;
|
||||
args.CreateDirectoryIfNotExists(destDir ?? String.Empty);
|
||||
|
||||
var srcDir = AdditionalFilesFromOriginal ? new FileInfo(args.FileName).DirectoryName : new FileInfo(args.WorkingFile).DirectoryName;
|
||||
|
||||
if (args.MoveFile(dest) == false)
|
||||
return -1;
|
||||
|
||||
if(AdditionalFiles?.Any() == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var diSrc = new DirectoryInfo(srcDir);
|
||||
foreach (var additional in AdditionalFiles)
|
||||
{
|
||||
foreach(var addFile in diSrc.GetFiles(additional))
|
||||
{
|
||||
try
|
||||
{
|
||||
string addFileDest = Path.Combine(destDir, addFile.Name);
|
||||
System.IO.File.Move(addFile.FullName, addFileDest, true);
|
||||
args.Logger?.ILog("Moved file: \"" + addFile.FullName + "\" to \"" + addFileDest + "\"");
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
args.Logger?.ILog("Failed moving file: \"" + addFile.FullName + "\": " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
args.Logger.WLog("Error moving additinoal files: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (DeleteOriginal && args.FileName != args.WorkingFile)
|
||||
{
|
||||
args.Logger?.ILog("Deleting orginal file: " + args.FileName);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -16,7 +16,7 @@ namespace VideoNodes.Tests
|
||||
[TestMethod]
|
||||
public void DetectBlackBars_Test_01()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\Fast Five (2011) Bluray-2160p.mkv";
|
||||
const string file = @"D:\videos\Dexter - New Blood - S01E02 - Storm of Fuck.mkv";
|
||||
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", new TestLogger());
|
||||
var vii = vi.Read(file);
|
||||
|
||||
@@ -35,7 +35,13 @@ namespace VideoNodes.Tests
|
||||
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
}
|
||||
[TestMethod]
|
||||
public void DetectBlackBars_Test_02()
|
||||
{
|
||||
var crop = DetectBlackBars.TestAboveThreshold(1920, 1080, 1920, 1072, 20);
|
||||
Assert.IsFalse(crop.crop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ namespace FileFlows.VideoNodes
|
||||
private string ffMpegExe;
|
||||
private ILogger Logger;
|
||||
|
||||
Regex rgxTitle = new Regex(@"(?<=((^[\s]+title[\s]+:[\s])))(.*?)$", RegexOptions.Multiline);
|
||||
Regex rgxDuration = new Regex(@"(?<=((^[\s]+DURATION(\-[\w]+)?[\s]+:[\s])))([\d]+:?)+\.[\d]{1,7}", RegexOptions.Multiline);
|
||||
Regex rgxDuration2 = new Regex(@"(?<=((^[\s]+Duration:[\s])))([\d]+:?)+\.[\d]{1,7}", RegexOptions.Multiline);
|
||||
Regex rgxAudioSampleRate = new Regex(@"(?<=((,|\s)))[\d]+(?=([\s]?hz))", RegexOptions.IgnoreCase);
|
||||
static Regex rgxTitle = new Regex(@"(?<=((^[\s]+title[\s]+:[\s])))(.*?)$", RegexOptions.Multiline);
|
||||
static Regex rgxDuration = new Regex(@"(?<=((^[\s]+DURATION(\-[\w]+)?[\s]+:[\s])))([\d]+:?)+\.[\d]{1,7}", RegexOptions.Multiline);
|
||||
static Regex rgxDuration2 = new Regex(@"(?<=((^[\s]+Duration:[\s])))([\d]+:?)+\.[\d]{1,7}", RegexOptions.Multiline);
|
||||
static Regex rgxAudioSampleRate = new Regex(@"(?<=((,|\s)))[\d]+(?=([\s]?hz))", RegexOptions.IgnoreCase);
|
||||
|
||||
public VideoInfoHelper(string ffMpegExe, ILogger logger)
|
||||
{
|
||||
@@ -62,64 +62,7 @@ namespace FileFlows.VideoNodes
|
||||
}
|
||||
|
||||
Logger.ILog("Video Information:" + Environment.NewLine + output);
|
||||
|
||||
var rgxStreams = new Regex(@"Stream\s#[\d]+:[\d]+(.*?)(?=(Stream\s#[\d]|$))", RegexOptions.Singleline);
|
||||
var streamMatches = rgxStreams.Matches(output);
|
||||
int streamIndex = 0;
|
||||
|
||||
|
||||
// get a rough estimate, bitrate: 346 kb/s
|
||||
var rgxBitrate = new Regex(@"(?<=(bitrate: ))[\d\.]+(?!=( kb/s))");
|
||||
var brMatch = rgxBitrate.Match(output);
|
||||
if (brMatch.Success)
|
||||
{
|
||||
vi.Bitrate = float.Parse(brMatch.Value) * 1_000; // to convert to b/s
|
||||
}
|
||||
|
||||
int subtitleIndex = 1;
|
||||
foreach (Match sm in streamMatches)
|
||||
{
|
||||
if (sm.Value.Contains(" Video: "))
|
||||
{
|
||||
var vs = ParseVideoStream(sm.Value, output);
|
||||
if (vs != null)
|
||||
{
|
||||
vs.Index = streamIndex;
|
||||
var match = Regex.Match(sm.Value, @"(?<=(Stream #))[\d]+:[\d]+");
|
||||
if (match.Success)
|
||||
vs.IndexString = match.Value;
|
||||
vi.VideoStreams.Add(vs);
|
||||
}
|
||||
}
|
||||
else if (sm.Value.Contains(" Audio: "))
|
||||
{
|
||||
var audio = ParseAudioStream(sm.Value);
|
||||
if (audio != null)
|
||||
{
|
||||
audio.Index = streamIndex;
|
||||
var match = Regex.Match(sm.Value, @"(?<=(Stream #))[\d]+:[\d]+");
|
||||
if (match.Success)
|
||||
audio.IndexString = match.Value;
|
||||
vi.AudioStreams.Add(audio);
|
||||
}
|
||||
}
|
||||
else if (sm.Value.Contains(" Subtitle: "))
|
||||
{
|
||||
var sub = ParseSubtitleStream(sm.Value);
|
||||
if (sub != null)
|
||||
{
|
||||
sub.Index = streamIndex;
|
||||
sub.TypeIndex = subtitleIndex;
|
||||
var match = Regex.Match(sm.Value, @"(?<=(Stream #))[\d]+:[\d]+");
|
||||
if (match.Success)
|
||||
sub.IndexString = match.Value;
|
||||
vi.SubtitleStreams.Add(sub);
|
||||
}
|
||||
++subtitleIndex;
|
||||
}
|
||||
++streamIndex;
|
||||
}
|
||||
|
||||
vi = ParseOutput(Logger, output);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -130,7 +73,69 @@ namespace FileFlows.VideoNodes
|
||||
return vi;
|
||||
}
|
||||
|
||||
VideoStream ParseVideoStream(string info, string fullOutput)
|
||||
public static VideoInfo ParseOutput(ILogger logger, string output)
|
||||
{
|
||||
var vi = new VideoInfo();
|
||||
var rgxStreams = new Regex(@"Stream\s#[\d]+:[\d]+(.*?)(?=(Stream\s#[\d]|$))", RegexOptions.Singleline);
|
||||
var streamMatches = rgxStreams.Matches(output);
|
||||
int streamIndex = 0;
|
||||
|
||||
|
||||
// get a rough estimate, bitrate: 346 kb/s
|
||||
var rgxBitrate = new Regex(@"(?<=(bitrate: ))[\d\.]+(?!=( kb/s))");
|
||||
var brMatch = rgxBitrate.Match(output);
|
||||
if (brMatch.Success)
|
||||
{
|
||||
vi.Bitrate = float.Parse(brMatch.Value) * 1_000; // to convert to b/s
|
||||
}
|
||||
|
||||
int subtitleIndex = 1;
|
||||
foreach (Match sm in streamMatches)
|
||||
{
|
||||
if (sm.Value.Contains(" Video: "))
|
||||
{
|
||||
var vs = ParseVideoStream(logger, sm.Value, output);
|
||||
if (vs != null)
|
||||
{
|
||||
vs.Index = streamIndex;
|
||||
var match = Regex.Match(sm.Value, @"(?<=(Stream #))[\d]+:[\d]+");
|
||||
if (match.Success)
|
||||
vs.IndexString = match.Value;
|
||||
vi.VideoStreams.Add(vs);
|
||||
}
|
||||
}
|
||||
else if (sm.Value.Contains(" Audio: "))
|
||||
{
|
||||
var audio = ParseAudioStream(sm.Value);
|
||||
if (audio != null)
|
||||
{
|
||||
audio.Index = streamIndex;
|
||||
var match = Regex.Match(sm.Value, @"(?<=(Stream #))[\d]+:[\d]+");
|
||||
if (match.Success)
|
||||
audio.IndexString = match.Value;
|
||||
vi.AudioStreams.Add(audio);
|
||||
}
|
||||
}
|
||||
else if (sm.Value.Contains(" Subtitle: "))
|
||||
{
|
||||
var sub = ParseSubtitleStream(sm.Value);
|
||||
if (sub != null)
|
||||
{
|
||||
sub.Index = streamIndex;
|
||||
sub.TypeIndex = subtitleIndex;
|
||||
var match = Regex.Match(sm.Value, @"(?<=(Stream #))[\d]+:[\d]+");
|
||||
if (match.Success)
|
||||
sub.IndexString = match.Value;
|
||||
vi.SubtitleStreams.Add(sub);
|
||||
}
|
||||
++subtitleIndex;
|
||||
}
|
||||
++streamIndex;
|
||||
}
|
||||
return vi;
|
||||
}
|
||||
|
||||
public static VideoStream ParseVideoStream(ILogger logger, string info, string fullOutput)
|
||||
{
|
||||
// Stream #0:0(eng): Video: h264 (High), yuv420p(tv, bt709/unknown/unknown, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn (default)
|
||||
string line = info.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries).First();
|
||||
@@ -154,22 +159,22 @@ namespace FileFlows.VideoNodes
|
||||
if (rgxDuration.IsMatch(info) && TimeSpan.TryParse(rgxDuration.Match(info).Value, out TimeSpan duration) && duration.TotalSeconds > 0)
|
||||
{
|
||||
vs.Duration = duration;
|
||||
Logger?.ILog("Video stream duration: " + vs.Duration);
|
||||
logger?.ILog("Video stream duration: " + vs.Duration);
|
||||
}
|
||||
else if (rgxDuration2.IsMatch(fullOutput) && TimeSpan.TryParse(rgxDuration2.Match(fullOutput).Value, out TimeSpan duration2) && duration2.TotalSeconds > 0)
|
||||
{
|
||||
vs.Duration = duration2;
|
||||
Logger?.ILog("Video stream duration: " + vs.Duration);
|
||||
logger?.ILog("Video stream duration: " + vs.Duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger?.ILog("Failed to read duration for VideoStream: " + info);
|
||||
logger?.ILog("Failed to read duration for VideoStream: " + info);
|
||||
}
|
||||
|
||||
return vs;
|
||||
}
|
||||
|
||||
AudioStream ParseAudioStream(string info)
|
||||
public static AudioStream ParseAudioStream(string info)
|
||||
{
|
||||
// Stream #0:1(eng): Audio: dts (DTS), 48000 Hz, stereo, fltp, 1536 kb/s (default)
|
||||
string line = info.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries).First();
|
||||
@@ -201,7 +206,7 @@ namespace FileFlows.VideoNodes
|
||||
|
||||
return audio;
|
||||
}
|
||||
SubtitleStream ParseSubtitleStream(string info)
|
||||
public static SubtitleStream ParseSubtitleStream(string info)
|
||||
{
|
||||
// Stream #0:1(eng): Audio: dts (DTS), 48000 Hz, stereo, fltp, 1536 kb/s (default)
|
||||
string line = info.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries).First();
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -44,6 +44,11 @@
|
||||
Gets or sets the processing priority of this library
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FileFlows.Shared.Models.LibraryFile.ExecutedNodes">
|
||||
<summary>
|
||||
Gets or sets a list of nodes that were executed against this library file
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:FileFlows.Shared.Validators.DefaultValidator">
|
||||
<summary>
|
||||
Used instead of null
|
||||
|
||||
Binary file not shown.
@@ -35,18 +35,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"NodaTime/3.0.9": {
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "4.7.1"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/NodaTime.dll": {
|
||||
"assemblyVersion": "3.0.9.0",
|
||||
"fileVersion": "3.0.9.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe/4.7.1": {},
|
||||
"FileFlows.Plugin/1.0.0": {
|
||||
"runtime": {
|
||||
"FileFlows.Plugin.dll": {}
|
||||
@@ -55,8 +43,7 @@
|
||||
"FileFlows.ServerShared/1.0.0": {
|
||||
"dependencies": {
|
||||
"FileFlows.Plugin": "1.0.0",
|
||||
"FileFlows.Shared": "1.0.0",
|
||||
"NodaTime": "3.0.9"
|
||||
"FileFlows.Shared": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"FileFlows.ServerShared.dll": {}
|
||||
@@ -93,20 +80,6 @@
|
||||
"path": "microsoft.extensions.objectpool/5.0.5",
|
||||
"hashPath": "microsoft.extensions.objectpool.5.0.5.nupkg.sha512"
|
||||
},
|
||||
"NodaTime/3.0.9": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-7KzJBkgSzLLyBXNYafDlnzlji3aB/8myvt5RJu5aaTFq6puVCq2WDJY9v9yDMg22+5or5IaKNItQ1jNA8nzQNA==",
|
||||
"path": "nodatime/3.0.9",
|
||||
"hashPath": "nodatime.3.0.9.nupkg.sha512"
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe/4.7.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-zOHkQmzPCn5zm/BH+cxC1XbUS3P4Yoi3xzW7eRgVpDR2tPGSzyMZ17Ig1iRkfJuY0nhxkQQde8pgePNiA7z7TQ==",
|
||||
"path": "system.runtime.compilerservices.unsafe/4.7.1",
|
||||
"hashPath": "system.runtime.compilerservices.unsafe.4.7.1.nupkg.sha512"
|
||||
},
|
||||
"FileFlows.Plugin/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -59,4 +59,6 @@ SMTP
|
||||
templating
|
||||
scriban
|
||||
github
|
||||
normalization
|
||||
normalization
|
||||
doesn''t
|
||||
*
|
||||
Binary file not shown.
Reference in New Issue
Block a user