请牛人指点:C#调用ffmpeg进行对WMV格式的视频快速无损剪辑合并,希望跳过帧内编码转换

zhu15951179298 2014-12-19 02:29:43
最近公司需要实现一个视频剪辑合并功能,要求整个流程必须在5秒以内做完,并且要保证剪辑出的视频音频质量完全无损,花了两天时间预研的结果远没有达标,现在将代码贴上,求CSDN的大牛们帮忙看看有没有什么好的办法,感激涕零!
代码要求在.net framework4.0版本下运行
现在最新研究到CompleteMethod3();
但是速度太慢了,希望可以快一些

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace VideoCutByFFmpeg
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
}
void Form1_Load(object sender, EventArgs e)
{
CompleteMethod3();
Application.Exit();
}

/// <summary>
/// 预研结果:
/// 1、可以将视频转换成WMV,时间分割精准到秒
/// 2、质量较原视频的音频稍有降低,视频的画面已经达标
/// 3、文件大小已在可控制范围内
/// 4、工作总时间有待进一步优化
/// 下一步预研工作:
/// 1、提升转换后的视频的音频质量
/// 2、优化文件大小
/// 3、网上曾有人遇到过转换后的视频在网络中播放时有卡顿现象,有待进一步测试
/// 4、优化工作总时间
/// 5、对其他视频的结果进行全面测试
/// </summary>
private void CompleteMethod3()
{
#region 初始化文件及路径
string inputPath = "E:/convert/123.wmv";
string outputmpgPath = "E:/convert/666.mpg";
string allFramePath = "E:/convert/456.mpg";
string outputPath = "E:/convert1/";
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ffmpeg.exe";
string arguments = "";
if (Directory.Exists(outputPath))
{
Directory.Delete(outputPath, true);
}
Directory.CreateDirectory(outputPath);
if (File.Exists(allFramePath))
{
File.Delete(allFramePath);
}
if (File.Exists(outputmpgPath))
{
File.Delete(outputmpgPath);
}
#endregion

#region 将原视频文件直接转换成MPEG格式
arguments = " -i " + inputPath + " -sameq -f mpeg " + outputmpgPath;
ProcessStartInfo psi = new ProcessStartInfo(path, arguments);
//psi.WindowStyle = ProcessWindowStyle.Hidden;
Process p = Process.Start(psi);
p.WaitForExit();
#endregion

#region 模拟建立视频分割区域
List<ClipItem> lstCI = new List<ClipItem>();
for (int i = 0; i < 3; i++)
{
ClipItem ci = new ClipItem();
ci.BeginTime = "00:00:" + i + "0";
ci.EndTime = "00:00:" + i + "5";
ci.DurationTime = "00:00:05";
lstCI.Add(ci);
}
#endregion

#region 采用建立的视频分割区域对转码后的MPEG视频进行分割
List<string> lstCut = new List<string>();
foreach (var item in lstCI)
{
arguments = " -ss " + item.BeginTime + " -vsync 0 -t " + item.DurationTime + " -i " + outputmpgPath + " -vcodec copy -acodec copy " + outputPath + "cut" + lstCI.IndexOf(item) + ".mpg";
psi = new ProcessStartInfo(path, arguments);
//psi.WindowStyle = ProcessWindowStyle.Hidden;
p = Process.Start(psi);
p.WaitForExit();
lstCut.Add(outputPath + "cut" + lstCI.IndexOf(item) + ".mpg");
}
#endregion

#region 将分割后的视频文件进行整理,以便于下面的合并操作
string allcut = "";
foreach (var item in lstCut)
{
allcut += item + "|";
}
allcut = allcut.Remove(allcut.Length - 1);
#endregion

#region 将分割好的视频进行合并
string allcutpath = outputPath + "allcut.mpg";
arguments = " -i concat:\"" + allcut + "\" -vcodec copy -acodec copy " + allcutpath;
psi = new ProcessStartInfo(path, arguments);
//psi.WindowStyle = ProcessWindowStyle.Hidden;
p = Process.Start(psi);
p.WaitForExit();
#endregion

#region 找到转换为WMV的方法,等待测试中
string allcuttoaviPath = "E:/convert1/allcut.wmv";
//arguments = " -i " + allcutpath + " -y -vcodec wmv2 -r 29.97 -qscale 6 -ab 192 -acodec libmp3lame -ac 2 -ar 44100 " + allcuttoaviPath;
arguments = " -i " + allcutpath + " -y -vcodec wmv2 -r 5 -qscale 6 -ab 192 -acodec libmp3lame -ac 2 -ar 44100 " + allcuttoaviPath;
psi = new ProcessStartInfo(path, arguments);
//psi.WindowStyle = ProcessWindowStyle.Hidden;
p = Process.Start(psi);
p.WaitForExit();
//ffmpeg.exe -i 3307-117.AVI -y -vcodec wmv2 -s 320X240 -b 200000 -r 29.97 -acodec wmav2 -ar 8000 ok.wmv
//高品质:ffmpeg -i infile -ab 128 -acodec libmp3lame -ac 1 -ar 22050 -r 29.97 -qscale 6 -y outfile
#endregion
}

private void TestMethod2()
{
#region 初始化文件及路径
string inputPath = "E:/convert/123.wmv";
string outputPath = "E:/convert/";
string cutpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ffmpeg1.exe";
string mergepath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ffmpeg.exe";
string arguments = "";
ProcessStartInfo psi;
Process p;
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
#endregion

#region 模拟建立视频分割区域
List<ClipItem> lstCI = new List<ClipItem>();
for (int i = 0; i < 3; i++)
{
ClipItem ci = new ClipItem();
ci.BeginTime = "00:00:" + i + "0";
ci.EndTime = "00:00:" + i + "5";
ci.DurationTime = "00:00:05";
lstCI.Add(ci);
}
#endregion

#region 采用建立的视频分割区域对转码后的MPEG视频进行分割
List<string> lstCut = new List<string>();
foreach (var item in lstCI)
{
//" -ss " + item.BeginTime + " -vsync 0 -t " + item.DurationTime + " -i " + allFramePath + " -vcodec copy -acodec copy " + outputPath + "cut" + lstCI.IndexOf(item) + ".mpg";
//-ss START -t DURATION -i INPUT -vcodec copy -acodec copy OUTPUT
arguments = "-ss " + item.BeginTime + " -t " + item.DurationTime + " -i " + inputPath + " -vcodec copy -acodec copy " + outputPath + "cut" + lstCI.IndexOf(item) + ".wmv";
//arguments = "-ss " + item.BeginTime + " -i " + inputPath + " -vcodec copy -acodec copy -t " + item.DurationTime + " " + outputPath + "cut" + lstCI.IndexOf(item) + ".wmv";
psi = new ProcessStartInfo(cutpath, arguments);
//psi.WindowStyle = ProcessWindowStyle.Hidden;
p = Process.Start(psi);
p.WaitForExit();
lstCut.Add(outputPath + "cut" + lstCI.IndexOf(item) + ".wmv");
}
#endregion

#region 将分割后的视频文件进行整理,以便于下面的合并操作
string allcut = "";
//foreach (var item in lstCut)
//{
// allcut += "file ‘" + item + "’\r\n";
//}
//allcut = allcut.Remove(allcut.Length - 2);
foreach (var item in lstCut)
{
allcut += item + "|";
}
allcut = allcut.Remove(allcut.Length - 1);
#endregion

#region 将分割好的视频进行合并
string fileListPah = outputPath + "list.txt";
if (File.Exists(fileListPah))
{
File.Delete(fileListPah);
}
File.Create(fileListPah).Close();
using (FileStream stream = File.Open(fileListPah, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
StreamWriter sw = new StreamWriter(stream);
sw.Write(allcut);
sw.Flush();
}
string allcutpath = outputPath + "allcut.wmv";
//ffmpeg -f concat -i 路径/ff.txt -c copy out.mp4
//arguments = "-f concat -i " + fileListPah + " -c copy " + allcutpath;
//arguments = "-f concat -i " + fileListPah + " " + allcutpath;
//arguments = " -i concat:" + allcut + " -vcodec copy -acodec copy " + allcutpath;
arguments = " -i concat:\"" + allcut + "\" -vcodec copy -acodec copy " + allcutpath;
psi = new ProcessStartInfo(mergepath, arguments);
//psi.WindowStyle = ProcessWindowStyle.Hidden;
p = Process.Start(psi);
p.WaitForExit();
#endregion
}
}

public class ClipItem
{
private string _BeginTime = "";

public string BeginTime
{
get { return _BeginTime; }
set { _BeginTime = value; }
}

private string _EndTime = "";

public string EndTime
{
get { return _EndTime; }
set { _EndTime = value; }
}

private string _DurationTime = "";

public string DurationTime
{
get { return _DurationTime; }
set { _DurationTime = value; }
}
}
}

ffmpeg必须要使用附件中的ffmpeg才可以运行成功,
运行时请将ffmpeg.exe放到“我的文档”下,
在E盘建立两个文件夹convert和convert1,
将要转换的视屏放到convert中取名123.wmv,
转换完成的结果是convert1中allcut.wmv文件,
测试的时候建议视屏文件的时间短一些但要大于30秒。
现在希望可以跳过代码中的帧内编码转换步骤,
希望直接对wmv格式的视频进行剪辑和合并。
以下是项目中用到的ffmpeg下载地址,论坛不能直接传附件只能给地址了(差点就找不到了,汗):
http://www.ddooo.com/softdown/17938.htm
...全文
430 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
ouyurong 2016-11-09
  • 打赏
  • 举报
回复
你好,你这个是在32位机子上运行的还是64位机子上运行的,我的机子是64位的,好像不行哦!

110,549

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧