/// <summary> /// tries to open the video source and gets the number of frames from it, or /// exits with an error /// </summary> /// <param name="videoSource">the AviSynth script</param> /// <param name="error">return parameter for all errors</param> /// <returns>true if the file could be opened, false if not</returns> protected void getInputProperties(VideoJob job) { //VapourSynthHelper vsHelper = new VapourSynthHelper(); //vsHelper.LoadScriptFile(job.Input); VSPipeInfo vsHelper = new VSPipeInfo(job.Input, job.VspipeArgs); fps_n = vsHelper.FpsNum; fps_d = vsHelper.FpsDen; NumberOfFrames = (ulong)vsHelper.TotalFreams; job.NumberOfFrames = NumberOfFrames; if (fps_n == job.FpsNum && fps_d == job.FpsDen) { return; } if (job.Vfr) { job.FpsNum = (uint)fps_n; job.FpsDen = (uint)fps_d; job.Fps = (fps_n + 0.0) / fps_d; return; } OKETaskException ex = new OKETaskException(Constants.fpsMismatchSmr); ex.progress = 0.0; ex.Data["SRC_FPS"] = ((double)job.FpsNum / job.FpsDen).ToString("F3"); ex.Data["DST_FPS"] = ((double)fps_n / fps_d).ToString("F3"); throw ex; }
/// <summary> /// tries to open the video source and gets the number of frames from it, or /// exits with an error /// </summary> /// <param name="videoSource">the AviSynth script</param> /// <param name="error">return parameter for all errors</param> /// <returns>true if the file could be opened, false if not</returns> protected void getInputProperties(VideoJob job) { //VapourSynthHelper vsHelper = new VapourSynthHelper(); //vsHelper.LoadScriptFile(job.Input); VSPipeInfo vsHelper = new VSPipeInfo(job.Input); fps_n = vsHelper.FpsNum; fps_d = vsHelper.FpsDen; numberOfFrames = (ulong)vsHelper.TotalFreams; // su.ClipLength = TimeSpan.FromSeconds((double)numberOfFrames / fps); }
public RpcJob(string sourceFile, VideoJob videoJob) { Input = sourceFile; Output = Path.ChangeExtension(sourceFile, "rpc"); RippedFile = videoJob.Output; TotalFrame = videoJob.NumberOfFrames; foreach (string arg in videoJob.VspipeArgs) { int pos = arg.IndexOf('='); string variable = arg.Substring(0, pos); string value = arg.Substring(pos + 1); Args[variable] = value; } }
public X264Encoder(VideoJob job) : base() { this.job = job; getInputProperties(job); executable = Path.Combine(Environment.SystemDirectory, "cmd.exe"); if (File.Exists(job.EncoderPath)) { this.X264Path = job.EncoderPath; } // 获取VSPipe路径 this.VspipePath = Initializer.Config.vspipePath; commandLine = BuildCommandline(job.EncodeParam, job.NumaNode, job.VspipeArgs); }
/// <summary> /// tries to open the video source and gets the number of frames from it, or /// exits with an error /// </summary> /// <param name="videoSource">the AviSynth script</param> /// <param name="error">return parameter for all errors</param> /// <returns>true if the file could be opened, false if not</returns> protected void getInputProperties(VideoJob job) { //VapourSynthHelper vsHelper = new VapourSynthHelper(); //vsHelper.LoadScriptFile(job.Input); VSPipeInfo vsHelper = new VSPipeInfo(job.Input, job.VspipeArgs); fps_n = vsHelper.FpsNum; fps_d = vsHelper.FpsDen; NumberOfFrames = (ulong)vsHelper.TotalFreams; if (fps_n != job.FpsNum || fps_d != job.FpsDen) { OKETaskException ex = new OKETaskException(Constants.fpsMismatchSmr); ex.progress = 0.0; ex.Data["SRC_FPS"] = ((double)job.FpsNum / job.FpsDen).ToString("F3"); ex.Data["DST_FPS"] = ((double)fps_n / fps_d).ToString("F3"); throw ex; } // su.ClipLength = TimeSpan.FromSeconds((double)numberOfFrames / fps); }
public void Start() { // TODO: 只考虑完整的视频压制流程 if (job.JobType != "video") { return; } VideoJob vjob = job as VideoJob; // 抽取音轨 FileInfo eacInfo = new FileInfo(".\\tools\\eac3to\\eac3to.exe"); if (!eacInfo.Exists) { throw new Exception("Eac3to 不存在"); } EACDemuxer eac = new EACDemuxer(eacInfo.FullName, vjob.config.InputFile); var audioTracks = eac.Extract((double progress, EACProgressType type) => { switch (type) { case EACProgressType.Analyze: vjob.config.Status = "轨道分析中"; vjob.config.ProgressValue = progress; break; case EACProgressType.Process: vjob.config.Status = "抽取音轨中"; vjob.config.ProgressValue = progress; break; case EACProgressType.Completed: vjob.config.Status = "音轨抽取完毕"; vjob.config.ProgressValue = progress; break; default: return; } }); // 默认列表是按照顺序来 string audioTrack = audioTracks[0].OutFileName; // 音频转码 List <string> audioFile = new List <string>(); foreach (var track in vjob.config.AudioTracks) { var audioOutput = audioTracks[track.TrackId]; string audioOutpath = audioOutput.OutFileName; if (track.Format.ToUpper() == "AAC") { vjob.config.Status = "音轨转码中"; vjob.config.ProgressValue = -1; if (audioOutput.FileExtension == ".flac") { AudioJob aDecode = new AudioJob("WAV"); aDecode.Input = audioOutput.OutFileName; aDecode.Output = "-"; FLACDecoder flac = new FLACDecoder(".\\tools\\flac\\flac.exe", aDecode); AudioJob aEncode = new AudioJob("AAC"); aEncode.Input = "-"; aEncode.Output = Path.ChangeExtension(audioOutpath, ".aac"); QAACEncoder qaac = new QAACEncoder(".\\tools\\qaac\\qaac.exe", aEncode, track.Bitrate); CMDPipeJobProcessor cmdpipe = CMDPipeJobProcessor.NewCMDPipeJobProcessor(flac, qaac); cmdpipe.start(); cmdpipe.waitForFinish(); audioOutpath = aEncode.Output; } } var audioFileInfo = new FileInfo(audioOutpath); if (audioFileInfo.Length < 1024) { // 无效音轨 // TODO: 提示用户不能封装 File.Move(audioOutpath, Path.ChangeExtension(audioOutpath, ".bak") + audioFileInfo.Extension); continue; } if (!track.SkipMuxing) { audioFile.Add(audioOutpath); } } vjob.config.Status = "获取信息中"; IJobProcessor processor = x265Encoder.init(vjob, vjob.config.EncoderParam); vjob.config.Status = "压制中"; vjob.config.ProgressValue = 0.0; processor.start(); processor.waitForFinish(); if (vjob.config.ContainerFormat != "") { // 封装 vjob.config.Status = "封装中"; FileInfo mkvInfo = new FileInfo(".\\tools\\mkvtoolnix\\mkvmerge.exe"); if (!mkvInfo.Exists) { throw new Exception("mkvmerge不存在"); } FileInfo lsmash = new FileInfo(".\\tools\\l-smash\\muxer.exe"); if (!lsmash.Exists) { throw new Exception("l-smash 封装工具不存在"); } AutoMuxer muxer = new AutoMuxer(mkvInfo.FullName, lsmash.FullName); muxer.ProgressChanged += progress => vjob.config.ProgressValue = progress; List <string> mergeList = new List <string> { vjob.config.InputFile + ".hevc", Path.ChangeExtension(vjob.config.InputFile, ".txt"), }; mergeList.AddRange(audioFile); muxer.StartMerge(mergeList, vjob.Output); } vjob.config.Status = "完成"; vjob.config.ProgressValue = 100; }