コード例 #1
0
ファイル: CameraController.cs プロジェクト: nomada2/RESTCam
        public HttpResponseMessage StartRecording([FromUri] VideoStartRequest startRequest)
        {
            if (startRequest == null || string.IsNullOrEmpty(startRequest.Source))
            {
                return
                    (GenerateJsonResponse(
                         new
                {
                    Started = false,
                    StartRequest = startRequest,
                    Error = "No source was specified. A source is required."
                }));
            }

            if (startRequest.MaxDurationSecs == 0)
            {
                startRequest.MaxDurationSecs = (5 * 60);
            }

            var existingKeys =
                FfmpegInstance.RunningInstances.Where(i => i.StartRequest.RecordingKey == startRequest.RecordingKey);

            foreach (var existingInstance in existingKeys)
            {
                existingInstance.Stop(null);
            }

            FfmpegInstance newInstance = new FfmpegInstance();

            newInstance.Start(startRequest);
            Console.WriteLine("Starting recording: " + Newtonsoft.Json.JsonConvert.SerializeObject(startRequest));

            return(GenerateJsonResponse(new { Started = true, StartRequest = startRequest }));
        }
コード例 #2
0
        public async Task <bool> Run(string inputFilePath, string outputFilePath, string animFramesDirPath, double framerate)
        {
            var videoProcess = new AnimationTaskCompileProcessVideo(FfmpegPath, new FfmpegCompatibilityOptions
            {
                TargetCompatibility = FfmpegCompatibilityOptions.OutputCompatibilityType.HighQualityLowCompatibility,
                OutputFramerate     = (int)framerate
            });


            string tmpOutputFilePath = $"{Path.GetDirectoryName(outputFilePath)}/{Path.GetFileName(outputFilePath)}.mp4";

            if (File.Exists(tmpOutputFilePath))
            {
                File.Delete(tmpOutputFilePath);
            }

            if (!await videoProcess.Run(inputFilePath, tmpOutputFilePath, animFramesDirPath, framerate))
            {
                return(false);
            }

            string outputPaletteFile = $"{Path.GetDirectoryName(outputFilePath)}\\{Path.GetFileNameWithoutExtension(outputFilePath)}_palette.png";

            var paletteFfmpeg = new FfmpegInstance(FfmpegPath);

            paletteFfmpeg.Options = new FfmpegRawOptions
            {
                RawParams = $"-i \"{tmpOutputFilePath}\" -vf palettegen \"{outputPaletteFile}\""
            };

            var paletteResult = await paletteFfmpeg.Start(null, null);

            if (paletteResult.ExitCode != 0)
            {
                Logger.Error("ffmpeg failed while generating a GIF palette for {InputFilePath}, where ffmpeg output {FfmpegConsoleOutputStream}", inputFilePath, string.Join("\n", paletteResult.OutputStreamData));
                return(false);
            }

            var videoFfmpeg = new FfmpegInstance(FfmpegPath);

            videoFfmpeg.Options = new FfmpegRawOptions
            {
                RawParams = $"-i \"{tmpOutputFilePath}\" -i \"{outputPaletteFile}\" -lavfi \"paletteuse\" \"{outputFilePath}\""
            };

            var ffmpegResult = await videoFfmpeg.Start(null, outputFilePath);

            if (ffmpegResult.ExitCode != 0)
            {
                Logger.Error("ffmpeg failed while converting a temporary mp4 to gif for {InputFilePath}, where ffmpeg output {FfmpegConsoleOutputStream}", inputFilePath, string.Join("\n", ffmpegResult.OutputStreamData));
                File.Delete(outputPaletteFile);
                return(false);
            }

            File.Delete(outputPaletteFile);
            File.Delete(tmpOutputFilePath);

            return(File.Exists(outputFilePath));
        }
コード例 #3
0
        public async Task <bool> Run(string inputFilePath, string outputFilePath, string animFramesDirPath, double framerate)
        {
            Logger.Verbose("Running ffmpeg to combine frames from {AnimFramesDir} into {OutputFile}", animFramesDirPath, outputFilePath);

            var ffmpegInstance = new FfmpegInstance(FfmpegPath);

            FfmpegOptions.OutputFramerate = (int)framerate;
            ffmpegInstance.Options        = FfmpegOptions;

            string inputPathFormat = Path.Combine(animFramesDirPath, $"{Path.GetFileNameWithoutExtension(inputFilePath)}_%04d.png");
            var    ffmpegResult    = await ffmpegInstance.Start(inputPathFormat, outputFilePath, () => this.Cancel);

            Logger.Verbose("Ran ffmpeg with parameters: {FfmpegParameters}", ffmpegResult.Args);

            if (ffmpegResult.ExitCode != 0 && !ffmpegResult.WasTerminated)
            {
                Logger.Error("Error occurred while running ffmpeg {@FfmpegOutput}", ffmpegResult.OutputStreamData);
                return(false);
            }

            return(true);
        }
コード例 #4
0
        public async Task <AnimationExtractionResult> ExtractFrames(string animationPath, string outputFolderPath, Func <bool> shouldTerminateDelegate = null)
        {
            string animationName      = Path.GetFileNameWithoutExtension(animationPath);
            string outputFramesFormat = Path.Combine(outputFolderPath, animationName) + "_%04d.png";

            double framerate = 0;

            using (MagickImageCollection gifFrames = new MagickImageCollection(animationPath))
            {
                foreach (var frame in gifFrames)
                {
                    if (shouldTerminateDelegate())
                    {
                        return(null);
                    }

                    framerate += frame.AnimationDelay / 100.0 / gifFrames.Count;
                }
            }

            framerate = 1.0 / framerate;

            var ffmpegInstance = new FfmpegInstance(FfmpegPath);

            ffmpegInstance.Options = new FfmpegRawOptions
            {
                RawParams = $"-i \"{animationPath}\" -vf fps={framerate} \"{outputFramesFormat}\""
            };

            var ffmpegResult = await ffmpegInstance.Start(null, null, shouldTerminateDelegate);

            if (shouldTerminateDelegate())
            {
                return(null);
            }

            if (ffmpegResult.ExitCode != 0)
            {
                Logger.Error("Failed to extract GIF frames for {InputAnimationPath} with ffmpeg, ffmpeg output was {@FfmpegOutput}", animationPath, ffmpegResult.OutputStreamData);
                return(null);
            }

            var animationFiles = Directory.EnumerateFiles(outputFolderPath).Where(f => Path.GetFileName(f).StartsWith(animationName + "_")).ToList();

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

            for (int i = 1; i <= animationFiles.Count; i++)
            {
                string originalIdxString = i.ToString();
                originalIdxString = new string('0', 4 - originalIdxString.Length) + originalIdxString;

                string correctedIdxString = (i - 1).ToString();
                correctedIdxString = new string('0', 4 - correctedIdxString.Length) + correctedIdxString;

                string originalFile  = $"{outputFolderPath}\\{animationName}_{originalIdxString}.png";
                string correctedFile = $"{outputFolderPath}\\{animationName}_{correctedIdxString}.png";
                File.Move(originalFile, correctedFile);


                outputFiles.Add(correctedFile);
            }

            if (DenoiseAmount > 0)
            {
                Logger.Verbose("Frame extraction complete, denoising by {DenoiseAmount}x", DenoiseAmount);

                foreach (var frame in outputFiles)
                {
                    if (shouldTerminateDelegate())
                    {
                        return(null);
                    }

                    using (MagickImage img = new MagickImage(frame))
                    {
                        for (int i = 0; i < DenoiseAmount; i++)
                        {
                            img.Despeckle();
                        }

                        img.Write(frame);
                    }
                }
            }

            return(new AnimationExtractionResult
            {
                Fps = framerate,
                ExtractedFiles = outputFiles
            });
        }
コード例 #5
0
        public async Task <AnimationExtractionResult> ExtractFrames(string animationPath, string outputFolderPath, Func <bool> shouldTerminateDelegate)
        {
            string animationName = Path.GetFileNameWithoutExtension(animationPath);

            var ffmpegInstance = new FfmpegInstance(FfmpegPath);

            ffmpegInstance.Options = new FfmpegRawOptions {
                RawParams = $"-i \"{animationPath}\" \"{outputFolderPath}\\{animationName}_%04d.png\""
            };

            var runInfo = await ffmpegInstance.Start(null, null, shouldTerminateDelegate);

            if (shouldTerminateDelegate())
            {
                return(null);
            }

            if (runInfo.ExitCode != 0)
            {
                Logger.Error("Running video frame extraction on {VideoPath} failed, where ffmpeg output: {FfmpegConsoleOutput}", animationPath, string.Join("\n", runInfo.OutputStreamData));
                return(null);
            }


            var ffmpegOutput = string.Join("\n", runInfo.OutputStreamData);

            var    fpsMatcher = new Regex(@"(\d+) fps");
            var    fpsMatch   = fpsMatcher.Match(ffmpegOutput);
            var    fpsString  = fpsMatch.Groups[1].Value;
            double fps        = double.Parse(fpsString);

            var durationMatcher = new Regex(@"Duration\: (\d+\:\d+\:\d+\.\d+)");
            var durationString  = durationMatcher.Match(ffmpegOutput).Captures[0].Value;
            var durationParts   = durationString.Split(new[] { ':', '.' });

            TimeSpan duration = new TimeSpan(0, int.Parse(durationParts[1]),
                                             int.Parse(durationParts[2]),
                                             int.Parse(durationParts[3]),
                                             int.Parse(durationParts[4]));

            int numFrames = (int)Math.Round(duration.TotalSeconds * fps);

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

            for (int i = 1; i <= numFrames; i++)
            {
                string originalIdxString = i.ToString();
                originalIdxString = new string('0', 4 - originalIdxString.Length) + originalIdxString;

                string correctedIdxString = (i - 1).ToString();
                correctedIdxString = new string('0', 4 - correctedIdxString.Length) + correctedIdxString;

                string originalFile  = $"{outputFolderPath}\\{animationName}_{originalIdxString}.png";
                string correctedFile = $"{outputFolderPath}\\{animationName}_{correctedIdxString}.png";
                File.Move(originalFile, correctedFile);


                outputFiles.Add(correctedFile);
            }

            return(new AnimationExtractionResult
            {
                Fps = fps,
                ExtractedFiles = outputFiles
            });
        }