/// <summary> /// 生成混流任务 /// </summary> /// <param name="param">音频输入地址</param> /// <param name="input"></param> /// <param name="output"></param> /// <param name="preset"></param> /// <param name="useHdr"></param> /// <param name="originInput"></param> /// <param name="extra">混流目标输出地址</param> /// <returns></returns> public static (string exefile, string args) Build(string param, string input, string output, Preset preset, bool useHdr, string originInput, string extra) { var baseDir = AppContext.EncodingContext.BaseDir; var(ext, _) = FileSelector.FileName.GetOutputExt(preset.MuxFormat); var muxOutput = FileSelector.FileName.RecalcOutputPath(input, extra, "_mux", ext); if (input == originInput) { muxOutput = extra; } var audioInput = param; if (preset.MuxFormat == OutputFormat.MKV) { var mkvmerge = Path.Combine(baseDir, "Libs\\mkvmerge.exe"); var mkvArgs = $"-o \"{muxOutput}\" -A \"{input}\" -D \"{audioInput}\""; return(mkvmerge, mkvArgs); } var ffmpegFile = Path.Combine(baseDir, "Libs\\ffmpeg.exe"); var extraArgs = ""; if (preset.MuxFormat == OutputFormat.MP4) { extraArgs = "-movflags faststart"; } var format = TaskArgBuilder.GetFormat(preset.MuxFormat); var args = $"-i \"{input}\" -i \"{audioInput}\" -map 0:v -map 1:a -c copy {extraArgs} -f {format} \"{muxOutput}\""; return(ffmpegFile, args); }
public static (string exefile, string args) Build(string param, string input, string output, Preset preset, bool useHdr, string originInput, string assInput) { var exeFileName = TaskArgBuilder.GetBaseEncoderFile(preset); string ioargs = TaskArgBuilder.GetIOArgs(input, output, preset); string gargs = TaskArgBuilder.GenericArgumentBuilder(preset, useHdr); var addArgs = new List <string> { preset.Decoder switch { Presets.Decoder.AVSW => "--avsw", Presets.Decoder.AVHW => "--avhw", } }; if (preset.IsSetOutputRes) { addArgs.Add("--output-res"); addArgs.Add($"{preset.OutputResWidth}x{preset.OUtputResHeight}"); } if (preset.IsSetAvSync && preset.AudioEncode != AudioEncode.None) { addArgs.Add("--avsync"); addArgs.Add(preset.AVSync switch { AVSync.Cfr => "cfr", AVSync.ForceCfr => "forcecfr", AVSync.Vfr => "vfr", });
public static (string exefile, string args) Build(string param, string input, string output, Preset preset, bool useHdr, string originInput, string extra) { var exeFileName = Path.Combine(AppContext.EncodingContext.BaseDir, "Libs\\ffmpeg.exe"); int transfer; int prim; int matrix; switch (param) { case "HDR10": prim = 9; transfer = 16; matrix = 9; break; case "HLG": prim = 9; transfer = 18; matrix = 9; break; case "SDR": default: prim = 1; transfer = 1; matrix = 1; break; } var format = TaskArgBuilder.GetFormat(preset.OutputFormat); var args = $"-i \"{input}\" -c copy " + $"-bsf:v hevc_metadata=colour_primaries={prim}:transfer_characteristics={transfer}:matrix_coefficients={matrix} " + $"-f {format} \"{output}\""; return(exeFileName, args); }
public static (string exefile, string args) Build(string param, string input, string output, Preset preset, bool useHdr, string originInput, string extra) { var tempFileList = new List <string>(); //临时文件 var baseDir = AppContext.EncodingContext.BaseDir; var workDir = Path.GetDirectoryName(output); //build bat var batName = Path.GetFileNameWithoutExtension(output) + "_ffmpegPipeBatTemp.bat"; var batFullname = Path.Combine(workDir, batName); //bat文件本身不记录在临时文件里 var batSb = new StringBuilder(); batSb.Append("@echo off\n"); var ffmpegFile = Path.Combine(baseDir, "Libs\\ffmpeg.exe"); var encoderFile = TaskArgBuilder.GetBaseEncoderFile(preset); var gargs = TaskArgBuilder.GenericArgumentBuilder(preset, useHdr); var addArgList = new List <string>(); if (preset.IsSetOutputRes) { addArgList.Add("--output-res"); addArgList.Add($"{preset.OutputResWidth}x{preset.OUtputResHeight}"); } if (preset.IsSetAvSync && preset.AudioEncode != AudioEncode.None) { addArgList.Add("--avsync"); addArgList.Add(preset.AVSync switch { AVSync.Cfr => "cfr", AVSync.ForceCfr => "forcecfr", AVSync.Vfr => "vfr", });
public static (string exefile, string args) Build(string param, string input, string output, Preset preset, bool useHdr, string originInput, string extra) { var tempFileList = new List <string>(); //临时文件 var baseDir = AppContext.EncodingContext.BaseDir; var workDir = Path.GetDirectoryName(output); var vpyName = Path.GetFileNameWithoutExtension(output) + "_vpyTemp.vpy"; var vpyFullname = Path.Combine(workDir, vpyName); tempFileList.Add(vpyFullname); var pyExtraLibName = Path.Combine(baseDir, "Libs\\site-packages"); var vpyFullContent = $"import sys\nsys.path.append(r'{pyExtraLibName}')\n\n" + param; TempFile.SaveTempFile(vpyFullname, vpyFullContent, false); //build bat var batName = Path.GetFileNameWithoutExtension(output) + "_batTemp.bat"; var batFullname = Path.Combine(workDir, batName); //bat文件本身不记录在临时文件里 var batSb = new StringBuilder(); batSb.Append("@echo off\n"); var vspipeFile = Path.Combine(baseDir, "Libs\\VSPipe.exe"); var encoderFile = TaskArgBuilder.GetBaseEncoderFile(preset); var gargs = TaskArgBuilder.GenericArgumentBuilder(preset, useHdr); if (preset.AudioEncode == AudioEncode.Copy) { //复制音频流 //--生成无音频流视频 var tempVideoExt = Path.GetExtension(output); var tempVideoOutput = Path.Combine(workDir, Path.GetFileNameWithoutExtension(output) + "_tempVideo" + tempVideoExt); var ioargs = TaskArgBuilder.GetIOArgs("-", tempVideoOutput, preset); batSb.Append($"\"{vspipeFile}\" --y4m \"{vpyFullname}\" - | \"{encoderFile}\" --y4m {ioargs} {gargs}\n"); tempFileList.Add(tempVideoOutput); //--混流 var ffmpegFile = Path.Combine(baseDir, "Libs\\ffmpeg.exe"); var format = TaskArgBuilder.GetFormat(preset.OutputFormat); var extraArgs = ""; if (preset.OutputFormat == OutputFormat.MP4) { extraArgs = "-movflags faststart"; } batSb.Append($"\"{ffmpegFile}\" -i \"{tempVideoOutput}\" -i \"{input}\" -map 0:v -map 1:a -c copy {extraArgs} -f {format} \"{output}\"\n"); } else if (preset.AudioEncode == AudioEncode.Encode) { //压制音频流 //--生成无音频流视频 var tempVideoExt = Path.GetExtension(output); var tempVideoOutput = Path.Combine(workDir, Path.GetFileNameWithoutExtension(output) + "_tempVideo" + tempVideoExt); var ioargs = TaskArgBuilder.GetIOArgs("-", tempVideoOutput, preset); batSb.Append($"\"{vspipeFile}\" --y4m \"{vpyFullname}\" - | \"{encoderFile}\" --y4m {ioargs} {gargs}\n"); tempFileList.Add(tempVideoOutput); //--qaac处理音频 var ffmpegFile = Path.Combine(baseDir, "Libs\\ffmpeg.exe"); var qaacFile = Path.Combine(baseDir, "Libs\\qaac64.exe"); var audioOutput = Path.Combine(workDir, Path.GetFileNameWithoutExtension(output) + "_tempAudio.m4a"); batSb.Append($"\"{ffmpegFile}\" -i \"{input}\" -vn -sn -v 0 -c:a pcm_s16le -f wav pipe: | \"{qaacFile}\" -q 2 --ignorelength -c {preset.AudioBitrate} - -o \"{audioOutput}\"\n"); tempFileList.Add(audioOutput); //--混流 var format = TaskArgBuilder.GetFormat(preset.OutputFormat); var extraArgs = ""; if (preset.OutputFormat == OutputFormat.MP4) { extraArgs = "-movflags faststart"; } batSb.Append($"\"{ffmpegFile}\" -i \"{tempVideoOutput}\" -i \"{audioOutput}\" -map 0:v -map 1:a -c copy {extraArgs} -f {format} \"{output}\"\n"); } else { //无音频流 var ioargs = TaskArgBuilder.GetIOArgs("-", output, preset); batSb.Append($"\"{vspipeFile}\" --y4m \"{vpyFullname}\" - | \"{encoderFile}\" --y4m {ioargs} {gargs}\n"); } foreach (var tempFile in tempFileList) { batSb.Append($"@del \"{tempFile}\"\n"); } batSb.Append($"@del \"{batFullname}\"\n"); //删除bat文件自身 //save bat TempFile.SaveTempFile(batFullname, batSb.ToString()); return(batFullname, ""); }