From 56f24eb4a1d382626ed925a539fa41ebd35f46fb Mon Sep 17 00:00:00 2001
From: flyself <1432593898@qq.com>
Date: Wed, 20 Oct 2021 14:30:04 +0800
Subject: [PATCH] =?UTF-8?q?FFmpeg=E8=B0=83=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/DownKyi.Core/FFmpeg/FFmpegHelper.cs | 232 ++++++++++++++++++++++++
1 file changed, 232 insertions(+)
create mode 100644 src/DownKyi.Core/FFmpeg/FFmpegHelper.cs
diff --git a/src/DownKyi.Core/FFmpeg/FFmpegHelper.cs b/src/DownKyi.Core/FFmpeg/FFmpegHelper.cs
new file mode 100644
index 0000000..b77bf99
--- /dev/null
+++ b/src/DownKyi.Core/FFmpeg/FFmpegHelper.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+
+namespace DownKyi.Core.FFmpeg
+{
+ public static class FFmpegHelper
+ {
+ private const string Tag = "PageToolboxDelogo";
+
+ ///
+ /// 合并音频和视频
+ ///
+ ///
+ ///
+ ///
+ public static bool MergeVideo(string video1, string video2, string destVideo)
+ {
+ string param = $"-i \"{video1}\" -i \"{video2}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\"";
+ if (video1 == null || !File.Exists(video1))
+ {
+ param = $"-i \"{video2}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\"";
+ }
+ if (video2 == null || !File.Exists(video2))
+ {
+ param = $"-i \"{video1}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\"";
+ }
+ if (!File.Exists(video1) && !File.Exists(video2)) { return false; }
+
+ // 如果存在
+ try { File.Delete(destVideo); }
+ catch (IOException e)
+ {
+ Console.WriteLine("MergeVideo()发生IO异常: {0}", e);
+ Logging.LogManager.Error(Tag, e);
+ return false;
+ }
+
+ ExcuteProcess("ffmpeg.exe", param, null, (s, e) => Console.WriteLine(e.Data));
+
+ try
+ {
+ if (video1 != null) { File.Delete(video1); }
+ if (video2 != null) { File.Delete(video2); }
+ }
+ catch (IOException e)
+ {
+ Console.WriteLine("MergeVideo()发生IO异常: {0}", e);
+ Logging.LogManager.Error(Tag, e);
+ }
+
+ return true;
+ }
+
+ ///
+ /// 拼接多个视频
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool ConcatVideo(string workingDirectory, List flvFiles, string destVideo)
+ {
+ // contact的文件名,不包含路径
+ string concatFileName = Guid.NewGuid().ToString("N") + "_concat.txt";
+ try
+ {
+ string contact = "";
+ foreach (string flv in flvFiles)
+ {
+ contact += $"file '{flv}'\n";
+ }
+
+ FileStream fileStream = new FileStream(workingDirectory + "/" + concatFileName, FileMode.Create);
+ StreamWriter streamWriter = new StreamWriter(fileStream);
+ //开始写入
+ streamWriter.Write(contact);
+ //清空缓冲区
+ streamWriter.Flush();
+ //关闭流
+ streamWriter.Close();
+ fileStream.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("ConcatVideo()发生异常: {0}", e);
+ Logging.LogManager.Error(Tag, e);
+ return false;
+ }
+
+ // ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mkv
+ // 加上-y,表示如果有同名文件,则默认覆盖
+ string param = $"-f concat -safe 0 -i {concatFileName} -c copy \"{destVideo}\" -y";
+ ExcuteProcess("ffmpeg.exe", param, workingDirectory, (s, e) => Console.WriteLine(e.Data));
+
+ // 删除临时文件
+ try
+ {
+ // 删除concat文件
+ File.Delete(workingDirectory + "/" + concatFileName);
+
+ foreach (string flv in flvFiles)
+ {
+ File.Delete(flv);
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("ConcatVideo()发生异常: {0}", e);
+ Logging.LogManager.Error(Tag, e);
+ }
+
+ return true;
+ }
+
+ ///
+ /// 去水印,非常消耗cpu资源
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void Delogo(string video, string destVideo, int x, int y, int width, int height, Action action)
+ {
+ // ffmpeg -i "video.mp4" -vf delogo=x=1670:y=50:w=180:h=70:show=1 "delogo.mp4"
+ string param = $"-i \"{video}\" -vf delogo=x={x}:y={y}:w={width}:h={height}:show=0 \"{destVideo}\" -hide_banner -y";
+ ExcuteProcess("ffmpeg.exe", param, null, (s, e) =>
+ {
+ Console.WriteLine(e.Data);
+ action.Invoke(e.Data);
+ });
+ }
+
+ ///
+ /// 从一个视频中仅提取音频
+ ///
+ /// 源视频
+ /// 目标音频
+ /// 输出信息
+ public static void ExtractAudio(string video, string audio, Action action)
+ {
+ // 抽取音频命令
+ // ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aac
+ // ffmpeg -i 3.mp4 -vn -y -acodec copy 3.m4a
+ string param = $"-i \"{video}\" -vn -y -acodec copy \"{audio}\" -hide_banner";
+ ExcuteProcess("ffmpeg.exe", param,
+ null, (s, e) =>
+ {
+ Console.WriteLine(e.Data);
+ action.Invoke(e.Data);
+ });
+ }
+
+ ///
+ /// 从一个视频中仅提取视频
+ ///
+ /// 源视频
+ /// 目标视频
+ /// 输出信息
+ public static void ExtractVideo(string video, string destVideo, Action action)
+ {
+ // 提取视频 (Extract Video)
+ // ffmpeg -i Life.of.Pi.has.subtitles.mkv -vcodec copy –an videoNoAudioSubtitle.mp4
+ string param = $"-i \"{video}\" -y -vcodec copy -an \"{destVideo}\" -hide_banner";
+ ExcuteProcess("ffmpeg.exe", param,
+ null, (s, e) =>
+ {
+ Console.WriteLine(e.Data);
+ action.Invoke(e.Data);
+ });
+ }
+
+ ///
+ /// 提取视频的帧,输出为图片
+ ///
+ ///
+ ///
+ ///
+ public static void ExtractFrame(string video, string image, uint number)
+ {
+ // 提取帧
+ // ffmpeg -i caiyilin.wmv -vframes 1 wm.bmp
+ string param = $"-i \"{video}\" -y -vframes {number} \"{image}\"";
+ ExcuteProcess("ffmpeg.exe", param, null, (s, e) => Console.WriteLine(e.Data));
+ }
+
+
+ ///
+ /// 执行一个控制台程序
+ ///
+ /// 程序名称
+ /// 参数
+ /// 工作路径
+ /// 输出重定向
+ private static void ExcuteProcess(string exe, string arg, string workingDirectory, DataReceivedEventHandler output)
+ {
+ using (var p = new Process())
+ {
+ p.StartInfo.FileName = exe;
+ p.StartInfo.Arguments = arg;
+
+ // 工作目录
+ if (workingDirectory != null)
+ {
+ p.StartInfo.WorkingDirectory = workingDirectory;
+ }
+
+ p.StartInfo.UseShellExecute = false; //输出信息重定向
+ p.StartInfo.CreateNoWindow = true;
+ p.StartInfo.RedirectStandardError = true;
+ p.StartInfo.RedirectStandardOutput = true;
+
+ // 将 StandardErrorEncoding 改为 UTF-8 才不会出现中文乱码
+ p.StartInfo.StandardOutputEncoding = System.Text.Encoding.UTF8;
+ p.StartInfo.StandardErrorEncoding = System.Text.Encoding.UTF8;
+
+ p.OutputDataReceived += output;
+ p.ErrorDataReceived += output;
+
+ p.Start(); //启动线程
+ p.BeginOutputReadLine();
+ p.BeginErrorReadLine();
+ p.WaitForExit(); //等待进程结束
+ }
+ }
+
+ }
+}