Unity 利用FFmpeg實現錄屏、直播推流、音頻視頻格式轉換、剪裁等功能

目錄

1、FFmpeg簡介。html

2、FFmpeg經常使用參數及命令。編程

3、FFmpeg在Unity 3D中的使用。數據結構

  一、FFmpeg 錄屏。框架

  二、FFmpeg 推流。tcp

  三、FFmpeg 其餘功能簡述。ide

 

1、FFmpeg簡介

對於FFmpeg,其官網上是這樣介紹的:oop

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 庫。其中:ui

 

libavcodec      是一個包含用於音頻/視頻編解碼器的解碼器和編碼器的庫。
libavutil       是一個包含簡化編程功能的庫,包括隨機數生成器,數據結構,數學例程,核心多媒體實用程序等等。
libavformat     是一個包含多媒體容器格式的解複用器和複用器的庫。
libavdevice     是一個包含輸入和輸出設備的庫,用於從許多常見的多媒體輸入/輸出軟件框架中獲取和呈現,包括Video4Linux,Video4Linux2,VfW和ALSA。
libavfilter     是一個包含媒體過濾器的庫。
libswscale      是一個執行高度優化的圖像縮放和色彩空間/像素格式轉換操做的庫。
libswresample   是一個執行高度優化的音頻重採樣,從新矩陣化和樣本格式轉換操做的庫。

2、FFmpeg經常使用參數及命令

一、命令的格式:編碼

ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_optionsoutput_url} ...

二、經常使用參數:

-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

三、經常使用命令

(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.jpegfoo-002.jpeg, 等

ffmpeg -i foo.avi -r 1 -s WxH -f image2 foo-%03d.jpeg

  

(2019.03.29 更新)

 3、FFmpeg在Unity 3D中的使用

有網友問我如何在Unity中使用FFmpeg呢,趁今天老大出差了,忙裏偷閒更新一下博客。

使用FFmpeg首先得有FFmpeg,能夠直接從官網免費下載,也能夠從Unity Store花費85美圓下載插件FFmpeg Unity Bind,

若是你有插件FFmpeg Unity Bind,那你就不用再往下看了,由於本文使用的就是FFmpeg Unity Bind的思想:用命令行參數實現FFmpeg的調用。

一、命令行調用FFmpeg的核心代碼以下:

     public static void Execute(string command)
        {
            if (isRunning)
                return;

            //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");

            }
        }

二、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 //-y 覆蓋已有文件 //-c //傳輸的圖像爲灰色的解決辦法,添加:-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_transport tcp rtsp://***/myid"; //輸入交換視頻和音頻的位置,畫面不卡頓了 //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 "+ ClientController.rtspId; //FFmpegCommands.DirectInput(command); //-re(輸入)主要用於模擬抓取設備或實時輸入流(例如,從文件讀取時)。不該與實際的抓取設備或實時輸入流一塊兒使用(它可能致使數據包丟失)。默認狀況下,ffmpeg嘗試儘快讀取輸入。此選項將減慢輸入讀取到輸入的本機幀速率。它對於實時輸出(例如直播)很是有用。 //string command = "-re -i \"" + path + "\" -vcodec libx264 -preset ultrafast -pix_fmt yuv420p -f rtsp -rtsp_transport tcp " +ClientController.rtspId;

 

三、完整源碼示例  

點擊這裏獲取你想要的源碼。

相關文章
相關標籤/搜索