コード例 #1
0
ファイル: FfmpegEncode.cs プロジェクト: n00mkrad/flowframes
        public static async Task FramesToVideo(string framesFile, string outPath, Interpolate.OutMode outMode, Fraction fps, Fraction resampleFps, float itsScale, VidExtraData extraData, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false)
        {
            if (logMode != LogMode.Hidden)
            {
                Logger.Log((resampleFps.GetFloat() <= 0) ? "Encoding video..." : $"Encoding video resampled to {resampleFps.GetString()} FPS...");
            }

            IoUtils.RenameExistingFile(outPath);
            Directory.CreateDirectory(outPath.GetParentDir());
            string[] encArgs = Utils.GetEncArgs(Utils.GetCodec(outMode), (Interpolate.current.ScaledResolution.IsEmpty ? Interpolate.current.InputResolution : Interpolate.current.ScaledResolution), Interpolate.current.outFps.GetFloat());

            string inArg    = $"-f concat -i {Path.GetFileName(framesFile)}";
            string linksDir = Path.Combine(framesFile + Paths.symlinksSuffix);

            if (Config.GetBool(Config.Key.allowSymlinkEncoding, true) && Symlinks.SymlinksAllowed())
            {
                if (await Symlinks.MakeSymlinksForEncode(framesFile, linksDir, Padding.interpFrames))
                {
                    inArg = $"-i \"{linksDir}/%{Padding.interpFrames}d{GetConcatFileExt(framesFile)}\"";
                }
            }

            string extraArgs = Config.Get(Config.Key.ffEncArgs);

            List <string> filters = new List <string>();

            if (resampleFps.GetFloat() >= 0.1f)
            {
                filters.Add($"fps=fps={resampleFps}");
            }

            if (Config.GetBool(Config.Key.keepColorSpace) && extraData.HasAllValues())
            {
                Logger.Log($"Applying color transfer ({extraData.colorSpace}).", true, false, "ffmpeg");
                filters.Add($"scale=out_color_matrix={extraData.colorSpace}");
                extraArgs += $" -colorspace {extraData.colorSpace} -color_primaries {extraData.colorPrimaries} -color_trc {extraData.colorTransfer} -color_range:v \"{extraData.colorRange}\"";
            }

            string vf = filters.Count > 0 ? $"-vf {string.Join(",", filters)}" : "";

            fps = fps / new Fraction(itsScale);

            string args = "";

            for (int i = 0; i < encArgs.Length; i++)
            {
                string pre  = i == 0 ? "" : $" && ffmpeg {AvProcess.GetFfmpegDefaultArgs()}";
                string post = (i == 0 && encArgs.Length > 1) ? $"-f null -" : outPath.Wrap();
                string fs   = (!isChunk && outMode == Interpolate.OutMode.VidMp4) ? $"-movflags +faststart" : "";
                args += $"{pre} -vsync 0 -r {fps} {inArg} {encArgs[i]} {vf} {GetAspectArg(extraData)} {extraArgs} -threads {Config.GetInt(Config.Key.ffEncThreads)} {fs} {post} ";
            }

            //string argsOld = $"-vsync 0 -r {fps} {inArg} {encArgs} {vf} {GetAspectArg(extraData)} {extraArgs} -threads {Config.GetInt(Config.Key.ffEncThreads)} {outPath.Wrap()}";
            await RunFfmpeg(args, framesFile.GetParentDir(), logMode, !isChunk);

            IoUtils.TryDeleteIfExists(linksDir);
        }
コード例 #2
0
        public static async Task MergeStreamsFromInput(string inputVideo, string interpVideo, string tempFolder, bool shortest)
        {
            if (!File.Exists(inputVideo) && !I.current.inputIsFrames)
            {
                Logger.Log("Warning: Input video file not found, can't copy audio/subtitle streams to output video!");
                return;
            }

            string containerExt = Path.GetExtension(interpVideo);
            string tempPath     = Path.Combine(tempFolder, $"vid{containerExt}");
            string outPath      = Path.Combine(tempFolder, $"muxed{containerExt}");

            IoUtils.TryDeleteIfExists(tempPath);
            File.Move(interpVideo, tempPath);
            string inName  = Path.GetFileName(tempPath);
            string outName = Path.GetFileName(outPath);

            string subArgs = "-c:s " + Utils.GetSubCodecForContainer(containerExt);

            bool   audioCompat = Utils.ContainerSupportsAllAudioFormats(I.current.outMode, GetAudioCodecs(inputVideo));
            bool   slowmo      = I.current.outItsScale != 0 && I.current.outItsScale != 1;
            string audioArgs   = audioCompat && !slowmo ? "" : await Utils.GetAudioFallbackArgs(inputVideo, I.current.outMode, I.current.outItsScale);

            if (!audioCompat && !slowmo)
            {
                Logger.Log("Warning: Input audio format(s) not fully supported in output container - Will re-encode.", true, false, "ffmpeg");
            }

            bool audio = Config.GetBool(Config.Key.keepAudio);
            bool subs  = Config.GetBool(Config.Key.keepSubs);
            bool meta  = Config.GetBool(Config.Key.keepMeta);

            if (!audio)
            {
                audioArgs = "-an";
            }

            if (!subs || (subs && !Utils.ContainerSupportsSubs(containerExt)))
            {
                subArgs = "-sn";
            }

            bool   isMkv       = I.current.outMode == I.OutMode.VidMkv;
            string mkvFix      = isMkv ? "-max_interleave_delta 0" : ""; // https://reddit.com/r/ffmpeg/comments/efddfs/starting_new_cluster_due_to_timestamp/
            string metaArg     = (isMkv && meta) ? "-map 1:t?" : "";     // https://reddit.com/r/ffmpeg/comments/fw4jnh/how_to_make_ffmpeg_keep_attached_images_in_mkv_as/
            string shortestArg = shortest ? "-shortest" : "";

            if (QuickSettingsTab.trimEnabled)
            {
                string otherStreamsName = $"otherStreams{containerExt}";

                string[] trim  = FfmpegExtract.GetTrimArgs();
                string   args1 = $"{trim[0]} -i {inputVideo.Wrap()} {trim[1]} -map 0 -map -0:v -map -0:d -c copy {audioArgs} {subArgs} {otherStreamsName}"; // Extract trimmed
                await RunFfmpeg(args1, tempFolder, LogMode.Hidden);

                string args2 = $"-i {inName} -i {otherStreamsName} -map 0:v:0 -map 1:a:? -map 1:s:? {metaArg} -c copy {audioArgs} {subArgs} {mkvFix} {shortestArg} {outName}"; // Merge interp + trimmed original
                await RunFfmpeg(args2, tempFolder, LogMode.Hidden);

                IoUtils.TryDeleteIfExists(Path.Combine(tempFolder, otherStreamsName));
            }
            else   // If trimming is disabled we can pull the streams directly from the input file
            {
                string args = $"-i {inName} -i {inputVideo.Wrap()} -map 0:v:0 -map 1:a:? -map 1:s:? {metaArg} -c copy {audioArgs} {subArgs} {mkvFix} {shortestArg} {outName}";
                await RunFfmpeg(args, tempFolder, LogMode.Hidden);
            }

            if (File.Exists(outPath) && IoUtils.GetFilesize(outPath) > 512)
            {
                File.Delete(tempPath);
                File.Move(outPath, interpVideo);
            }
            else
            {
                File.Move(tempPath, interpVideo);   // Muxing failed, move unmuxed video file back
            }
        }