|
@@ -52,7 +52,8 @@ namespace BatchProcess
|
|
|
private const string OP_CONVERT_FLAC_TO_AAC = "convert_flac_to_aac";
|
|
|
private const string OP_CONVERT_LIB_FLAC_TO_AAC = "convert_lib_flac_to_aac";
|
|
|
private const string OP_CONVERT_LIB_FLAC_TO_AAC_IN_DIR = "convert_lib_flac_to_aac_in_dir";
|
|
|
- private const string OP_CONVERT_LIB_SUBSET_TO_MP4_IN_DIR = "op_convert_lib_subset_to_mp4_in_dir";
|
|
|
+ private const string OP_CONVERT_LIB_SUBSET_TO_MP4_IN_DIR = "convert_lib_subset_to_mp4_in_dir";
|
|
|
+ private const string OP_SCAN_LIB_NO_COVER = "scan_lib_no_cover";
|
|
|
|
|
|
private static void RealMain(string[] args)
|
|
|
{
|
|
@@ -90,6 +91,8 @@ namespace BatchProcess
|
|
|
Console.WriteLine($" * {OP_CONVERT_LIB_SUBSET_TO_MP4_IN_DIR} <libDir> [subset]");
|
|
|
Console.WriteLine($" Convert to mp4(static cover) and copy tags to output, default subset is AAC_Q1.00");
|
|
|
Console.WriteLine($" libDir/Album/subset/Track.m4a -> libDir/Album/subset_MP4/Track.mp4");
|
|
|
+ Console.WriteLine($" * {OP_SCAN_LIB_NO_COVER} <libDir> [pattern] [...]");
|
|
|
+ Console.WriteLine($" Scan files in lib find no cover, pattern default *.flac");
|
|
|
Console.WriteLine($"");
|
|
|
Console.WriteLine($" + More on demand");
|
|
|
return;
|
|
@@ -121,11 +124,38 @@ namespace BatchProcess
|
|
|
case OP_CONVERT_LIB_FLAC_TO_AAC: ConvertLibFlacToAac(argsToOp); break;
|
|
|
case OP_CONVERT_LIB_FLAC_TO_AAC_IN_DIR: ConvertLibFlacToAacInDir(argsToOp); break;
|
|
|
case OP_CONVERT_LIB_SUBSET_TO_MP4_IN_DIR: ConvertLibSubsetToMp4InDir(argsToOp); break;
|
|
|
+ case OP_SCAN_LIB_NO_COVER: ScanLibNoCover(argsToOp); break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// impl
|
|
|
|
|
|
+ private static void ScanLibNoCover(string[] args)
|
|
|
+ {
|
|
|
+ if (args.Length < 1) throw new ArgumentException("args least need 1");
|
|
|
+
|
|
|
+ var libDir = args[0];
|
|
|
+
|
|
|
+ var patterns = args.Length > 1
|
|
|
+ ? args.Skip(1).ToArray()
|
|
|
+ : new[] { "*.flac" };
|
|
|
+
|
|
|
+ if (false == Directory.Exists(libDir)) throw new DirectoryNotFoundException($"lib dir `{libDir}' not found.");
|
|
|
+
|
|
|
+ foreach (var discDir in Directory.GetDirectories(libDir))
|
|
|
+ {
|
|
|
+ var trackFiles = Microsoft.VisualBasic.FileIO.FileSystem.GetFiles(discDir, Microsoft.VisualBasic.FileIO.SearchOption.SearchTopLevelOnly, patterns);
|
|
|
+
|
|
|
+ foreach (var file in trackFiles)
|
|
|
+ {
|
|
|
+ using var t = TagLib.File.Create(file);
|
|
|
+ var hasCover = t.Tag.Pictures.Any(p => p.Type == PictureType.FrontCover);
|
|
|
+
|
|
|
+ if (!hasCover) Console.WriteLine(file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static void ConvertLibSubsetToMp4InDir(string[] args)
|
|
|
{
|
|
|
if (args.Length < 1) throw new ArgumentException("args least need 1");
|
|
@@ -154,8 +184,6 @@ namespace BatchProcess
|
|
|
|
|
|
if (coverBytes == null) { Console.WriteLine($"WARN: skip. no cover in `{track}'"); continue; }
|
|
|
|
|
|
-
|
|
|
-
|
|
|
var tmp = Path.GetTempFileName();
|
|
|
File.WriteAllBytes(tmp, coverBytes);
|
|
|
|
|
@@ -171,7 +199,7 @@ namespace BatchProcess
|
|
|
"-i",track,
|
|
|
"-map_metadata","-1","-map_chapters","-1",
|
|
|
"-shortest",
|
|
|
-
|
|
|
+
|
|
|
"-vf","scale=-1:480,pad=ceil(iw/2)*2:ceil(ih/2)*2",
|
|
|
|
|
|
"-c:v","h264","-pix_fmt","yuv420p",
|
|
@@ -179,7 +207,7 @@ namespace BatchProcess
|
|
|
"-crf","28","-bf","1250","-g","1250","-keyint_min","250",
|
|
|
|
|
|
"-c:a","copy",
|
|
|
-
|
|
|
+
|
|
|
outFile
|
|
|
};
|
|
|
|
|
@@ -190,7 +218,6 @@ namespace BatchProcess
|
|
|
FileName = "ffmpeg",
|
|
|
CreateNoWindow = false,
|
|
|
UseShellExecute = false,
|
|
|
-
|
|
|
}
|
|
|
};
|
|
|
foreach (var item in ffMpegArgs) process.StartInfo.ArgumentList.Add(item);
|