ffmpeg 简单应用

说明

版本信息

1
ffmpeg version 2021-09-30-git-3ee4502753-essentials_build-www.gyan.dev Copyright (c) 2000-2021 the FFmpeg developers
  • ffmpeg、ffprobe、ffplay 三件套
  • ffmpeg 处理视频的流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 _______              ______________
| | | |
| input | demuxer | encoded data | decoder
| file | ---------> | packets | -----+
|_______| |______________| |
v
_________
| |
| decoded |
| frames |
|_________|
________ ______________ |
| | | | |
| output | <-------- | encoded data | <----+
| file | muxer | packets | encoder
|________| |______________|

一些功能

1. 查看视频信息

(1) 查看视频整体的信息

1
ffprobe -show_format input.mp4
  • 时长、比特率
1
Duration: 00:00:06.78, start: 0.000000, bitrate: 14865 kb/s
  • 流信息
1
2
3
4
5
6
7
8
Stream #0:0[0x1](und): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p(tv, smpte170m/bt470bg/smpte170m, progressive), 1080x1920, 14831 kb/s, 30 fps, 30 tbr, 1000k tbn (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : SoundHandler
vendor_id : [0][0][0][0]

(2) 查看视频的帧信息

  • 如下 test_1s.mp4 为一个时长 1s 的视频文件
  • 输出所有帧的信息(包括视频帧和音频帧)
    • -of xml:输出为 xml 格式
1
ffprobe -show_frames -of xml test_1s.mp4 > info_all.xml

视频帧信息

  • json 格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"media_type": "video",
"stream_index": 0,
"key_frame": 1, // 是否是关键帧
"pts": 0,
"pts_time": "0.000000",
"pkt_dts": 0,
"pkt_dts_time": "0.000000",
"best_effort_timestamp": 0,
"best_effort_timestamp_time": "0.000000",
"pkt_duration": 33333,
"pkt_duration_time": "0.033333",
"pkt_pos": "791",
"pkt_size": "223934",
"width": 1080,
"height": 1920,
"pix_fmt": "yuv420p",
"pict_type": "I",
"coded_picture_number": 0,
"display_picture_number": 0,
"interlaced_frame": 0,
"top_field_first": 0,
"repeat_pict": 0,
"color_range": "tv",
"color_space": "smpte170m",
"color_primaries": "bt470bg",
"color_transfer": "smpte170m",
"chroma_location": "left"
}

select_streams

  • 选项
    • v:视频
    • a:音频
    • v:1: 音频流,而且 index=1
  • 只输出视频帧的信息
    • -of json:输出为 json 格式
1
ffprobe -select_streams v -show_frames -of json test_1s.mp4 > infos.json

show_entries

  • 只显示给定的属性
    • 例如只显示这一帧开始播放的时间帧号
1
2
3
ffprobe -select_streams v -show_frames ^
-show_entries frame=pts_time,coded_picture_number ^
-of xml test_1s.mp4 > infos.xml
  • 根据给定的帧数找到对应的时间戳
    • 找到第 30 帧的时间戳
      • 帧从 0 开始编号
    • 视频较大时很慢
1
2
3
ffprobe -select_streams v -show_frames ^
-show_entries frame=pts_time,coded_picture_number ^
-of xml test_1s.mp4 | findstr "coded_picture_number=\"29\"" > ans.xml

2. 按时间剪辑

(1) 视频剪辑

  • 如果选项放在 -i 之前那就是作为 input 选项,之后就是作为 output 选项
1
ffmpeg -i input.mp4 -s 0 -t 3.33 -vcodec copy -acodec copy output.mp4
  • -i:输入文件
  • -s(input/output):从哪里时间开始
  • -to(input/output):到哪个时间停止
    • -t(input/output):持续多久时间(和 -to 互斥,-t 优先级更高)
  • -vcodec copy:不对视频进行重新编码
  • -acodec copy:不对音频进行重新编码
  • 时间的格式
    • 55:55 seconds
    • 0.2:0.2 seconds
    • 23.189:23.189 seconds
    • 200ms:200 milliseconds (= 0.2s)
    • 200000us:200000 microseconds (= 0.2s)
    • 12:03:45:12 hours, 03 minutes and 45 seconds

(2) 音频剪辑

1
ffmpeg -vn -i a.mp3 -s 0 -t 3.33 b.mp3

3. 合并视频

  • mp4 转 ts
1
2
3
ffmpeg -i p1.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 1.ts
ffmpeg -i p2.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 2.ts
ffmpeg -i p3.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 3.ts
  • 拼接,转 mp4
1
ffmpeg -i "concat:1.ts|2.ts|3.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4
  • 删除中间 ts 文件
    1
    del *.ts

4. 分离视频与音频

  • -an(input/output):阻挡所有音频流
  • -vn(input/output):阻挡所有视频流
  • 输出视频
1
ffmpeg -an -i input.mp4 -vcodec copy audio_mutex.mp4
  • 输出音频
1
ffmpeg -vn -i input.mp4 -acodec copy only_audio.aac

5. 音视频合并

1
2
ffmpeg -i audio_mutex.mp4 -i only_audio.aac ^
-c:v copy -c:a aac -strict experimental combine.mp4
  • 如果音频长于视频,则输出视频长度和音频一样,缺失的视频用最后一帧补全
  • 如果视频长于音频,则输出视频长度和视频一样,缺失的音频为无声

(1) 音频循环播放直至视频结束

1
2
3
4
ffmpeg -stream_loop -1 -i xue.m4a -i pintu.mp4 -shortest ^
-vcodec copy -acodec copy ^
-map 1:v:0 -map 0:a:0 ^
out.mp4
  • -stream_loop(input):表示流循环次数
    • -1:无限循环
    • 1:循环一次,表示让当前输入流循环一次,一共播放两次
  • -shortest
    • 短的流结束则输入结束
  • -map 1:v:0 -map 0:a:0
    • 使用第 1 号输入流的视频作为第 0 号输出流的视频
    • 使用第 0 号输入流的音频作为第 0 号输出流的音频

6. 视频加速

  • 如下例子是对音视频都加速 1.1 倍
1
ffmpeg -hwaccel cuda -i input.mp4 -vf setpts=PTS/1.1 -af atempo=1.1 output_1.1.mp4
  • -hwaccel cuda:使用 GPU 加速
  • 查看可用硬件
1
ffmpeg -hwaccels