­

音影片基本概念和FFmpeg的簡單入門

寫在前面

最近正好有音影片編輯的需求,雖然之前粗略的了解過FFmpeg不過肯定是不夠用的,藉此重新學習下;

基本概念

容器/文件(Conainer/File):

即特定格式的多媒體文件,一般來說一個影片文件是由影片,音頻,字幕等按特地的格式/規則組合到一起的,常見如:

mp4
flv
mkv
avi

媒體流(Stream):

表示時間軸上的一段連續數據,如一段聲音數據、一段影片數據或一段字幕數據,可以是壓縮的,也可以是非壓縮的,壓縮的數據需要關聯特定的編解碼器。

數據幀/數據包(Frame/Packet):

通常,一個媒體流是由大量的數據幀組成的,對於壓縮數據,幀對應著編解碼器的最小處理單元,分屬於不同媒體流的數據幀交錯存儲於容器之中。

一般: Frame對應壓縮前的數據,Packet對應壓縮後的數據。

編解碼器(Codec):

影片和音頻都需要經過編碼,才能保存成文件。編解碼器是指以幀為單位實現壓縮數據和原始數據之間的相互轉換的;

編碼:原始數據->壓縮數據;

解碼:壓縮數據->原始數據;

不同的編碼格式(CODEC),有不同的壓縮率,會導致文件大小和清晰度的差異。

常用的影片編碼格式如下:

H.262
H.264
H.265

示例:原始圖形YUV數據用H.264編碼成H264幀

image-20220420174551776

常用的音頻編碼格式如下:

MP3
AAC

示例:原始聲音PCM數據用AAC編碼器編碼成AAC幀(是的音頻也有幀)

image-20220420174752168

復用(mux):

把不同的流按照某種容器的規則放入容器,這種行為叫做復用(mux)

image-20220420173433070

解復用(mux):

把不同的流從某種容器中解析出來,這種行為叫做解復用(demux)

image-20220420173514115

幀率(Frame rate):

n幀率也叫幀頻率,用FPS表示。幀率是影片文件中每一秒的幀數,肉眼想看到連續移動影像至少需要15幀。

一般電影的幀率為24;

碼率(Bit Rate):

比特率(也叫碼率,數據率)是一個確定整體影片/音頻品質的參數,秒為單位處理的位數,碼率和影片品質成正比,在影片文件中中比特率用bps(bit per second)來表達。

碼率越低,表示壓縮程度越高,畫質越差。

碼率越高,影片品質相對越高,影片文件也就越大。

FFmpeg

FFmpeg是一個很多的項目,包括很多組件:

  • ffmpeg——一個命令行工具,用來對影片文件轉換格式,也支援對電視卡即時編碼
  • ffserver——一個HTTP多媒體即時廣播流伺服器,支援時光平移
  • ffplay——一個簡單的播放器,基於SDL與FFmpeg庫
  • libavcodec——包含全部FFmpeg音頻/影片編解碼庫
  • libavformat——包含demuxers和muxer庫
  • libavutil——包含一些工具庫
  • libpostproc——對於影片做前處理的庫
  • libswscale——對於影片作縮放的庫

我們一般說的的FFmpeg 是指FFmpeg 的命令行工具;

第一條FFmpeg命令

ffmpeg -y -i input.mp4 -acodec copy -vcodec libx264 -s 720x1280 output.avi

參數解析

-y # 全局參數,等於npm -y 
-i input.mp4 #輸入文件,FFmpeg命令有位置之分, -i 之前是輸入參數,之後是輸出參數
-acodec copy #輸出文件參數,複製音頻編碼而不用重新編碼
-vcodec libx26 #輸出文件參數,重新用libx26編碼(比較慢耗性能)
-s 720x1280 #輸出參數,
output.avi #輸出文件
可以看到,FFmpeg一般分為這五個部分,大家參考上面命令對號入座
    全局參數
    輸入文件參數
    輸入文件
    輸出文件參數
    輸出文件

所以這條命令的含義是:把影片input.mp4不修改音頻的情況下用libx26編碼音頻,同時解析度改成720*1280,格式改成avi;

影片資訊

左:input.mp4 ,右:output.avi

可以看到影片文件已經完成了命令操作轉換;

image-20220421111033369

FFmpeg常用參數

-c:指定編碼器

-c copy:直接複製,不經過重新編碼

-c:v:指定影片編碼器

-c:a:指定音頻編碼器

-i:指定輸入文件

-an:去除音頻流

-vn: 去除影片流,不處理影片

-preset:指定輸出的影片品質,會影響文件的生成速度,有以下幾個可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。

-y:不經過確認,輸出時直接覆蓋同名文件。

-s: size 設置幀大小 格式為WXH 預設160X128.下面的簡寫也可以直接使用:Sqcif 128X96 qcif 176X144 cif 252X288 4cif 704X576

-b: bitrate 設置比特率,預設200kb/s

-vcodec: codec 強制使用codec編解碼方式。 如果用copy表示原始編解碼數據直接被拷貝。

-filter:  影片過濾器,如 -filter:v "crop=w:h:x:y"用過濾器v裁剪影片
		 w - 源影片中裁剪的矩形的寬度
		 h – 矩形的高度。
		 x – 我們想自源影片中裁剪的矩形的 x 坐標 。
		 y – 矩形的 y 坐標。
		 
-aspect:設置橫縱比 4:3 16:9 或 1.3333 1.7777

-ss:position 搜索到指定的時間 [-]hh:mm:ss[.xxx]的格式也支援,比如用來指定剪切開始時間

FFmpeg命令處理流程

我們還是以這條命令為例,分析FFmpeg命令對影片的處理經過哪些流程

ffmpeg -y -i input.mp4 -acodec copy -vcodec libx264 -s 720x1280 output.avi

我們看圖:

image-20220421151232836

我們看到命令處理一般分成5個步驟

  1. 解復用:把容器文件解析成編碼的數據包;
  2. 解碼:解碼器把數據包解碼成數據幀;
  3. filter進行幀處理:把1080 * 1920的數據幀處理成720 * 1280
  4. 重新編碼:編碼器libx264重新把數據幀編碼成編碼的數據包;
  5. 復用:把數據包按格式avi封裝;

這個簡單流程比較重要,要瞭然於心;

FFmpeg常用命令

列印影片基本資訊

$ ffmpeg -i input.mp4 -hide_banner

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: mp42mp41isomavc1
    creation_time   : 2021-05-29T16:51:47.000000Z
  Duration: 00:00:30.61, start: 0.000000, bitrate: 5932 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1080x1920, 5672 kb/s, 60 fps, 60 tbr, 60 tbn (default)
    Metadata:
      creation_time   : 2021-05-29T16:51:47.000000Z
      handler_name    : L-SMASH Video Handler
      vendor_id       : [0][0][0][0]
      encoder         : AVC Coding
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 253 kb/s (default)
    Metadata:
      creation_time   : 2021-05-29T16:51:47.000000Z
      handler_name    : L-SMASH Audio Handler
      vendor_id       : [0][0][0][0]
At least one output file must be specified

轉換格式修改解析度

ffmpeg -y -i input.mp4  -s 720x1280 output.avi

影片靜音處理(移除音頻)

ffmpeg -i input.mp4 -an quiet.mp4

從影片中提取圖片

ffmpeg -i input.mp4 -r 1 -f image2 -ss 00:00:10 -t 2 image-%2d.png
  • -r – 設置幀速度。即,每秒提取幀到影像的數字。默認值是 25。

  • -f – 表示輸出格式,即,在我們的實例中是影像。

  • image-%2d.png – 表明我們如何想命名提取的影像。在這個實例中,命名應該像這樣image-01.png、image-02.png、image-03.png 等等開始。如果你使用 %3d,那麼影像的命名像 image-001.png、image-002.png 等等開始。

添加/修改封面

ffmpeg -y -i input.mp4 -i cover.png -map 0 -map 1 -c copy -disposition:v:1 attached_pic cover_output.mp4

如果需要把影片第一幀截出來坐封面,那就先提取

ffmpeg -ss 00:00:01 -i input.mp4  -f image2  cover.png

提取影片里的音頻文件

ffmpeg -i input.mp4 -vn -c:a copy output.aac

裁剪影片

ffmpeg -i input.mp4 -filter:v "crop=640:480:120:240" cut.mp4
  • -filter:v – 表示影片過濾器。

  • crop – 表示裁剪過濾器。

  • w – 我們想自源影片中裁剪的矩形的寬度。

  • h – 矩形的高度。

  • x – 我們想自源影片中裁剪的矩形的 x 坐標 。

  • y – 矩形的 y 坐標。

影片截取

ffmpeg -i input.mp4 -ss 00:00:05 -codec copy -t 10 cutout.mp4
  • -ss 開始時間

  • -t 10,截取十秒

影片切割拆分成多個

ffmpeg -i input.mp4 -t 00:00:13 -c copy part1.mp4 -ss 00:00:13 -codec copy part2.mp4
  • -t 00:00:13 表示從影片的開始到影片的第 30 秒創建一部分影片。

  • -ss 00:00:13 為影片的下一部分顯示開始時間戳。它意味著第 2 部分將從第 30 秒開始,並將持續到原始影片文件的結尾。

影片合併拼接

ffmpeg -i "concat:part1.mp4|part2.mp4" -c:a copy -c:v copy combine.mp4

設置視屏屏蔽寬高

ffmpeg -i input.mp4 -aspect 4:3 4_3.mp4

通常使用的高寬比是:

  • 16:9
  • 4:3
  • 16:10
  • 5:4
  • 2:21:1
  • 2:35:1
  • 2:39:1

添加字幕

ffmpeg -i input.mp4 -i subtitle.srt -c copy output.mkv

subtitle.srt 是字幕文件,然後這裡條件的是軟字幕比較快

總結

根據項目需要,簡單學習了下音影片的非常基本的概念和FFmpeg的基本使用,留個記錄;

[參考]

//www.ruanyifeng.com/blog/2020/01/ffmpeg.html

//zhuanlan.zhihu.com/p/67878761

廖慶富影片教程

Tags: