Unity利⽤FFmpeg实现录屏、直播推流、⾳频视频格式转换、剪裁等功能
⽬录
⼀、FFmpeg简介。
⼆、FFmpeg常⽤参数及命令。
三、FFmpeg在Unity 3D中的使⽤。
  1、FFmpeg 录屏。
  2、FFmpeg 推流。
  3、FFmpeg 其他功能简述。
⼀、FFmpeg简介
对于FFmpeg,其上是这样介绍的:
FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created.
FFmpeg能够实现对视频⾳频编码、解码、转码、流传输等等⼀系列功能。它包含有libavcodec, libavutil, libavformat, libavfilter, libavdevice, libswscale,libswresample 库。其中:
libavcodec      是⼀个包含⽤于⾳频/视频编解码器的解码器和编码器的库。
libavutil      是⼀个包含简化编程功能的库,包括随机数⽣成器,数据结构,数学例程,核⼼多媒体实⽤程序等等。
libavformat    是⼀个包含多媒体容器格式的解复⽤器和复⽤器的库。
libavdevice    是⼀个包含输⼊和输出设备的库,⽤于从许多常见的多媒体输⼊/输出软件框架中获取和呈现,包括Video4Linux,Video4Linux2,VfW和ALSA。
libavfilter    是⼀个包含媒体过滤器的库。
libswscale      是⼀个执⾏⾼度优化的图像缩放和⾊彩空间/像素格式转换操作的库。
libswresample  是⼀个执⾏⾼度优化的⾳频重采样,重新矩阵化和样本格式转换操作的库。
⼆、FFmpeg常⽤参数及命令
1、命令的格式:
ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...
2、常⽤参数:
-f fmt (input/output) 强制设定输⼊或输出⽂件格式。通常会⾃动检测输⼊⽂件的格式,并从输出⽂件的⽂件扩展名猜测格式,因此⼤多数情况下不需要这个选项。
-i url (input)          输⼊
-y (global)            在没有请求的情况下覆盖输出⽂件。
-n (global)            不要覆盖输出⽂件,如果指定的输出⽂件已经存在,则会⽴即退出。
-stream_loop number  设定输⼊流循环的次数。循环0表⽰没有循环,循环1表⽰⽆限循环
-codec/-c              设置编码格式
-r fps                  设置帧速率
-vcodec codec (output) 设置视频编码格式,同-codec:v
-pix_fmt format        设置像素格式
-ar freq                设置⾳频采样频率
-aq q (output)        设置⾳频质量
-acodec codec        设置⾳频编解码器,同-codec:a
3、常⽤命令
(1)将视频的帧速率改为24
ffmpeg -i input.avi -r 24 output.avi
(2)视频格式转换,将avi转成mp4
ffmpeg -i input.avi output.mp4
(3)从视频中提取⾳频
ffmpeg -i test.mp4 -acodec libmp3lame output.mp3
(4)视频剪切
ffmpeg -ss 00:00:15 -t 00:00:05 -i input.mp4 -vcodec copy -acodec copy output.mp4
(5)视频添加Logo
ffmpeg -i input.mp4 -i Logo.png -filter_complex overlay output.mp4
(6)视频去掉Logo
ffmpeg -i input.mp4 -vf delogo=0:0:220:90:100:1 output.mp4
(7)将100张图⽚合成视频,并为其添加背景⾳频(注意:图⽚要放在同⼀个⽂件夹下,并将图⽚按001--100的格式命名)
ffmpeg -i 001.mp3 -i %3d.jpg -s 1024x768 -author fy -vcodec mpeg4 darkdoor.avi
(8)将视频每隔⼀秒抽取⼀张图⽚,保存名字为foo-001.jpeg, foo-002.jpeg, 等
ffmpeg -i foo.avi -r 1 -s WxH -f image2 foo-%03d.jpeg
(2019.03.29 更新)
三、FFmpeg在Unity 3D中的使⽤
有⽹友问我如何在Unity中使⽤FFmpeg呢,趁今天⽼⼤出差了,忙⾥偷闲更新⼀下博客。
使⽤FFmpeg⾸先得有FFmpeg,可以直接从官⽹免费下载,也可以从Unity Store花费85美元下载插件FFmpeg Unity Bind,
如果你有插件FFmpeg Unity Bind,那你就不⽤再往下看了,因为本⽂使⽤的就是FFmpeg Unity Bind的思想:⽤命令⾏参数实现FFmpeg的调⽤。
1、命令⾏调⽤FFmpeg的核⼼代码如下:
    public static void Execute(string command)
{
//Clear output buffer
buffer = new StringBuilder(short.MaxValue);
new Thread(() =>
{
isRunning = true;
Thread.CurrentThread.IsBackground = true;
//Execute binary
p = new Process();
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = binaryPath;
p.StartInfo.Arguments = command;
p.StartInfo.RedirectStandardInput = true;//这句⼀定需要,⽤于模拟该进程控制台的输⼊
p.OutputDataReceived += (s, e) =>
{
callback(FFmpegParser.COMMAND_CODE + FFmpegParser.PROGRESS_CODE + AppendLog(e.Data));
};
p.ErrorDataReceived += (s, e) =>
{
if (!string.IsNullOrEmpty(e.Data) && e.Data.ToLower().Contains("error"))
callback(FFmpegParser.ERROR_CODE + AppendLog(e.Data));
else
callback(FFmpegParser.COMMAND_CODE + FFmpegParser.PROGRESS_CODE + AppendLog(e.Data));
};
p.Start();
callback(FFmpegParser.COMMAND_CODE + FFmpegParser.START_CODE + "\nStarted\n");
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
if (isStopProcessWhatIthink)
{
callback(FFmpegParser.COMMAND_CODE + FFmpegParser.SUCCESS_CODE + AppendLog("主动关闭 FFmpeg 进程") );                    isStopProcessWhatIthink = false;
}
else
{
callback(FFmpegParser.COMMAND_CODE +
(p.ExitCode == 0 ?
FFmpegParser.SUCCESS_CODE + AppendLog("Success!") :
FFmpegParser.FAILURE_CODE + AppendLog("Failure. Search details above")));
p.Close();
}
callback(FFmpegParser.COMMAND_CODE + FFmpegParser.FINISH_CODE + "\nFinished\n");
isRunning = false;
}).Start();
}
///<summary>
///主动退出进程
///</summary>
public static void CloseFFmpegProcess()
{
if (p!=null)
{
try
{
p.StandardInput.WriteLine("q");//在这个进程的控制台中模拟输⼊q,⽤于暂停录制
p.Close();
p.Dispose();
isRunning = false;
isStopProcessWhatIthink = true;
p = null;
UnityEngine.Debug.Log("主动退出FFmpeg进程");
}
catch (Exception)
{
UnityEngine.Debug.Log("No process to kill");
}
}
else
{
UnityEngine.Debug.Log("FFmpeg process is null");writeline方法的作用
}
}
2、FFmpeg 录屏、推流常⽤命令
//推流命令
//-re -i C:\output.mp4  -vcodec libx264 -acodec copy  -f flv -y rtmp://***/live/chid
//拉流
/
/-i rtmp://127.0.0.1/live/chid -acodec copy -vcodec copy -f flv -y chid.mp4
//-i rtmp://127.0.0.1/live/chid -c copy dump.flv
// rtsp 推流
// -i C:\output.mp4  -vcodec libx264 -f rtsp rtsp://***/myid
//-f gdigrab -i desktop -vcodec libx264 -preset ultrafast -acodec libmp3lame -ar 44100 -ac 1 -f rtsp rtsp://***/myid
//推摄像头
//-f dshow -i video="HD Pro Webcam C920" -vcodec libx264 -acodec copy -preset:v ultrafast -tune:v zerolatency -f rtsp rtsp://***/myid        //⾳视频录制
//-f dshow -video_size 1680x1050 -framerate 30 -pixel_format yuv420p -i audio="麦克风 (HD Pro Webcam C920)" av-out.mp4
//-f fmt    指定格式(⾳视频的格式)
/
/dshow
//-i        输⼊
//-vcodec  强制使⽤codec编解码⽅式('copy' to copy stream)
//libx264
//-acodec  指定⾳频编码('copy' to copy stream)
//copy
//-preset
//-tune
//传输的图像为灰⾊的解决办法,添加:-pix_fmt yuv420p
//录制桌⾯:desktop
//录制窗⼝:title=窗⼝名
/
/ av_interleaved_write_frame(): Broken pipe 问题:在-f rtsp后⾯加⼀个-rtsp_transport tcp
//录制整个程序窗⼝
//string command = "-f gdigrab -i title=test -vcodec libx264 -preset ultrafast -pix_fmt yuv420p -acodec libmp3lame -ar 44100 -ac 1 -f rtsp -rtsp_transport tcp rtsp://***/myid";
//录制某⼀区域(这⾥是摄像头区域)
//-offset_x 10 -offset_y 20 -video_size 640x480 从屏幕的(10,20)点处开始,抓取640x480的屏幕
//-s 640x480  指定分辨率 (640x480)
//-r 60 设置帧率(和程序的fps保持⼀致,解决Past duration 0.692253 too large的问题)
//string command = "-f gdigrab -offset_x 920 -offset_y 85 -video_size 320*240 -s 320*240 -i title=test -vcodec libx264 -preset ultrafast -pix_fmt yuv420p -r 60 -acodec libmp3lame -ar 44100 -ac 1 -f rtsp -rtsp_transport tcp rtsp://***/myid";
//string command = "-f gdigrab -offset_x 920 -offset_y 85 -video_size 320*240 -s 320*240 -i title=test -
f dshow -i audio=\""+ micName + "\" -vcodec libx264 -preset ultrafast -pix_fmt yuv420p -r 60 -acodec aac -ar 16000 -ac 1 -f rtsp -rtsp_tran        //输⼊交换视频和⾳频的位置,画⾯不卡顿了
//string command = "-f dshow -i audio=\"" + micName + "\" -f gdigrab -offset_x 920 -offset_y 85 -video_size 320*240 -s 320*240 -i title=test -vcodec libx264 -preset ultrafast -pix_fmt yuv420p -f rtsp -rtsp_transport tcp "+ spI        //FFmpegCommands.DirectInput(command);
//-re(输⼊)主要⽤于模拟抓取设备或实时输⼊流(例如,从⽂件读取时)。不应与实际的抓取设备或实时输⼊流⼀起使⽤(它可能导致数据包丢失)。默认情况下,ffmpeg尝试尽快读取输⼊。此选项将减慢输⼊读取到输⼊的本机帧速率。它对        //string command = "-re -i \"" + path + "\" -vcodec libx264 -preset ultrafast -pix_fmt yuv420p -f rtsp -rtsp_transport tcp " +spId;
3、完整源码⽰例 
点击获取你想要的源码。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。