高手略过吧,功能太简单,我自己都不好意思。。
这个是我自己的需要,做产品类的短视频,东搞西搞剪辑啊啥的,特别麻烦,所以先搞这个最简版,以后再一步步丰富功能。
需求:几张图片生成视频,视频长度以文案内容生成的语音为准。
c#准备数据即视频每一帧的图片和文案生成的语音,最后调用ffmpeg生成视频,顺序如下:
1、准备数据文件,约定第一行为文案文本,用这个生成语音文件,作视频配音,其他行为图片文件名。
2、解析数据文件,拿到文案文本和图片数组
private bool Parse()
{
if (!System.IO.File.Exists("source\\data.txt"))
{
log("找不到数据文件data.txt");
return false;
}
int i = 0;
Image img;
ImgFileList = new List();
foreach (string line in System.IO.File.ReadLines("source\\data.txt"))
{
if (i++ == 0)
{
wenzi = line;
continue;
}
if (!System.IO.File.Exists(line))
{
log("文件:" + line + ",不存在");
continue;
}
img = Image.FromFile(line);
if (img == null)
{
log("文件:" + line + ",不是图片");
continue;
}
img.Dispose();
ImgFileList.Add(line);
}
return ImgFileList.Count > 0;
}
3,调用百度api,生成语音,存放到data\ee.mp3,返回语音长度。
private bool GetBaiDuAudio(string str,out int len,out string filename)
{
//这里换成你自己的百度key
const string API_KEY = "asdfasdfasdfasfdasfd";
const string SECRET_KEY = "asdfasdfasfdasfd";
var client = new Baidu.Aip.Speech.Tts(API_KEY, SECRET_KEY);
client.Timeout = 60000; // 修改超时时间
// 可选参数
var option = new Dictionary()
{
{"spd", 5}, // 语速
{"vol", 5}, // 音量
{"per", 103}, // 发音人,4:情感度丫丫童声
};
var result = client.Synthesis(str, option);
if (result.ErrorCode == 0) // 或 result.Success
{
//取得当前路径
string path = System.AppDomain.CurrentDomain.BaseDirectory;
if (!Directory.Exists(path + "data"))
{
Directory.CreateDirectory(path + "data");
}
File.WriteAllBytes("data\\ee.mp3", result.Data);
len = Mp3.GetLength("data\\ee.mp3");
filename = "data\\ee.mp3";
return true;
}
len = 0;
filename = "";
return false;
}
这里吐槽下百度生成的mp3,ffmpeg -i ee.mp3,居然拿不到长度,为了拿到这个长度,费了好长时间,获取mp3长度代码如下:
public class APIClass
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
// 获取短文件名
public static extern int GetShortPathName(
string lpszLongPath,
string shortFile,
int cchBuffer
);
[DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Auto)]
public static extern int mciSendString(
string lpstrCommand,
string lpstrReturnString,
int uReturnLength,
int hwndCallback
);
}
class Mp3
{
public static int GetLength(string filename)
{
string Name = "";
Name = Name.PadLeft(260, Convert.ToChar(" "));
APIClass.GetShortPathName(filename, Name, Name.Length);
Name = GetCurrPath(Name);
Name = "open " + Convert.ToChar(34) + Name + Convert.ToChar(34) + " alias media";
APIClass.mciSendString(Name, "", 0, 0);
string durLength = "";
durLength = durLength.PadLeft(128, Convert.ToChar(" "));
APIClass.mciSendString("status media length", durLength, durLength.Length, 0);
APIClass.mciSendString("close media", "", 128, 0);
APIClass.mciSendString("close all", "", 128, 0);
durLength = durLength.Trim();
if (durLength == "") return 0;
return (int)(Convert.ToDouble(durLength));
}
private static string GetCurrPath(string name)
{
if (name.Length < 1) return "";
name = name.Trim();
name = name.Substring(0, name.Length - 1);
return name;
}
}
Mp3.GetLength函数返回的是毫秒。
4、根据mp3的长度来计算生成多少帧图片,源图片每张又生成多少张,最后生成图片。
图片总数:mp3长度/40,1000/40=25,我们按照每秒25帧来计算。
private void CreateImg()
{
//audion是百度音频长度,单位毫秒
//几张图片平均分布,按照每秒25帧来算是,就是40毫秒一张图片
int photon = audiolen / ImgFileList.Count / 40;
string file, extname, newfile;
int n;
int counta = 1;
//在data目录下生成1-n.jpg
for (int i = 0; i < ImgFileList.Count; i++)
{
file = ImgFileList[i];
n = file.LastIndexOf(".");
extname = file.Substring(n, file.Length - n);
for (int j = 0; j < photon; j++)
{
newfile = "data\\" + counta + extname;
File.Copy(file, newfile);
counta++;
}
}
}
5,调用ffmpeg命令行生成视频
命令:ffmpeg -f image2 -i data\\%d.jpg -i data\\ee.mp3 data\output.mp4
private string CreateVideo()
{
string DstFile = "data\\output.mp4";
string strCmd = string.Format("-f image2 -i {0} -i {1} {2} -y", "data\\%d.jpg", audiofile, DstFile);
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "ffmpeg.exe";//要执行的程序名称
p.StartInfo.Arguments = " " + strCmd;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = false;//可能接受来自调用程序的输入信息
p.StartInfo.RedirectStandardOutput = false;//由调用程序获取输出信息
p.StartInfo.RedirectStandardError = false;//重定向标准错误输出
p.StartInfo.CreateNoWindow = false;//不显示程序窗口
p.Start();//启动程序
p.WaitForExit();//等待程序执行完退出进程
if (System.IO.File.Exists(DstFile))
{
return DstFile;
}
return "";
}
6、运行图面
至此视频文件就生成了,视频长度与音乐长度完全匹配。
项目源码:https://download.csdn.net/download/xchenbb/87608144