Skip to content

Commit 7e4b687

Browse files
committed
add ffmpeg part
1 parent b82a745 commit 7e4b687

10 files changed

Lines changed: 528 additions & 68 deletions

File tree

VideoDevelopment/.DS_Store

6 KB
Binary file not shown.

VideoDevelopment/Android音视频开发/1.音视频基础知识.md

Lines changed: 99 additions & 10 deletions
Large diffs are not rendered by default.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
音视频同步原理
2+
===
3+
4+
5+
为什么需要音视频同步?
6+
7+
媒体数据经过解复用流程后,音频/视频解码便是独立的,也是独立播放的。而在音频流和视频流中,其播放速度都是有相关信息指定的:
8+
- 视频:帧率,表示视频一秒显示的帧数。
9+
- 音频:采样率,表示音频一秒播放的样本的个数。
10+
11+
从帧率及采样率,即可知道视频/音频播放速度。声卡和显卡均是以一帧数据来作为播放单位,如果单纯依赖帧率及采样率来进行播放,在理想条件下,应该是同步的,不会出现偏差。
12+
13+
以一个44.1KHz的AAC音频流和24FPS的视频流为例:
14+
15+
一个AAC音频frame每个声道包含1024个采样点,则一个frame的播放时长(duration)为:(1024/44100)×1000ms = 23.22ms;一个视频frame播放时长(duration)为:1000ms/24 = 41.67ms。理想情况下,音视频完全同步。
16+
但实际情况下,如果用上面那种简单的方式,慢慢的就会出现音视频不同步的情况,要不是视频播放快了,要么是音频播放快了。可能的原因如下:
17+
18+
一帧的播放时间,难以精准控制。音视频解码及渲染的耗时不同,可能造成每一帧输出有一点细微差距,长久累计,不同步便越来越明显。(例如受限于性能,42ms才能输出一帧)
19+
20+
音频输出是线性的,而视频输出可能是非线性,从而导致有偏差。
21+
22+
媒体流本身音视频有差距。(特别是TS实时流,音视频能播放的第一个帧起点不同)
23+
24+
所以,解决音视频同步问题,引入了时间戳:
25+
26+
首先选择一个参考时钟(要求参考时钟上的时间是线性递增的);
27+
28+
编码时依据参考时钟上的给每个音视频数据块都打上时间戳;
29+
30+
播放时,根据音视频时间戳及参考时钟,来调整播放。
31+
32+
所以,视频和音频的同步实际上是一个动态的过程,同步是暂时的,不同步则是常态。以参考时钟为标准,放快了就减慢播放速度;播放快了就加快播放的速度。
33+
34+
### DTS、PTS
35+
36+
- DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
37+
38+
- PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。
39+
40+
当视频流中没有 B 帧时,通常 DTS 和 PTS 的顺序是一致的。但如果有 B 帧时,就回到了我们前面说的问题:解码顺序和播放顺序不一致了,即视频输出是非线性的。
41+
42+
比如一个视频中,帧的显示顺序是:I B B P,因为B帧解码需要依赖P帧,因此这几帧在视频流中的顺序可能是:I P B B,这时候就体现出每帧都有 DTS 和 PTS 的作用了。DTS 告诉我们该按什么顺序解码这几帧图像,PTS 告诉我们该按什么顺序显示这几帧图像。流中P帧在B帧之前,但显示确实在B帧之后。
43+
44+
45+
实现音视频同步,在播放时,需要选定一个参考时钟,读取帧上的时间戳,同时根据的参考时钟来动态调节播放。现在已经知道时间戳就是PTS,那么参考时钟的选择一般来说有以下三种:
46+
47+
- 将视频同步到音频上:就是以音频的播放速度为基准来同步视频。
48+
- 将音频同步到视频上:就是以视频的播放速度为基准来同步音频。
49+
- 将视频和音频同步外部的时钟上:选择一个外部时钟为基准,视频和音频的播放速度都以该时钟为标准。
50+
51+
当播放源比参考时钟慢,则加快其播放速度,或者丢弃;快了,则延迟播放。
52+
这三种是最基本的策略,考虑到人对声音的敏感度要强于视频,频繁调节音频会带来较差的观感体验,且音频的播放时钟为线性增长,所以一般会以音频时钟为参考时钟,视频同步到音频上。
53+
54+
调整策略可以尽量采用渐进的方式,因为音视频同步是一个动态调节的过程,一次调整让音视频PTS完全一致,没有必要,且可能导致播放异常较为明显。
55+
56+
调整策略仅仅对早到的或晚到的数据块进行延迟或加快处理,有时候是不够的。如果想要更加主动并且有效地调节播放性能,需要引入一个反馈机制,也就是要将当前数据流速度太快或太慢的状态反馈给“源”,让源去放慢或加快数据流的速度。
57+
58+
59+
60+
---
61+
62+
- 邮箱 :charon.chui@gmail.com
63+
- Good Luck!
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
FFmpeg常用命令行
2+
===
3+
### ffmpeg
4+
5+
1.分离视频音频流
6+
7+
ffmpeg -i input_file -vcodec copy -an output_file_video  //分离视频流
8+
ffmpeg -i input_file -acodec copy -vn output_file_audio  //分离音频流
9+
10+
2.视频解复用
11+
12+
ffmpeg –i test.mp4 –vcodec copy –an –f m4v test.264
13+
ffmpeg –i test.avi –vcodec copy –an –f m4v test.264
14+
15+
3.视频转码
16+
17+
ffmpeg –i test.mp4 –vcodec h264 –s 352*278 –an –f m4v test.264 //转码为码流原始文件
18+
ffmpeg –i test.mp4 –vcodec h264 –bf 0 –g 25 –s 352*278 –an –f m4v test.264 //转码为码流原始文件
19+
ffmpeg –i test.avi -vcodec mpeg4 –vtag xvid –qsame test_xvid.avi //转码为封装文件
20+
//-bf B帧数目控制,-g 关键帧间隔控制,-s 分辨率控制
21+
22+
4.视频封装
23+
24+
ffmpeg –i video_file –i audio_file –vcodec copy –acodec copy output_file
25+
26+
5.视频剪切
27+
28+
ffmpeg –i test.avi –r 1 –f image2 image-%3d.jpeg //提取图片
29+
ffmpeg -ss 0:1:30 -t 0:0:20 -i input.avi -vcodec copy -acodec copy output.avi //剪切视频
30+
//-r 提取图像的频率,-ss 开始时间,-t 持续时间
31+
32+
6.视频录制
33+
34+
ffmpeg –i rtsp://192.168.3.205:5555/test –vcodec copy out.avi
35+
36+
7.YUV序列播放
37+
38+
ffplay -f rawvideo -video_size 1920x1080 input.yuv
39+
40+
8.YUV序列转AVI
41+
42+
ffmpeg –s w*h –pix_fmt yuv420p –i input.yuv –vcodec mpeg4 output.avi
43+
44+
常用参数说明:
45+
46+
主要参数: -i 设定输入流 -f 设定输出格式 -ss 开始时间 视频参数: -b 设定视频流量,默认为200Kbit/s -r 设定帧速率,默认为25 -s 设定画面的宽与高 -aspect 设定画面的比例 -vn 不处理视频 -vcodec 设定视频编解码器,未设定时则使用与输入流相同的编解码器 音频参数: -ar 设定采样率 -ac 设定声音的Channel数 -acodec 设定声音编解码器,未设定时则使用与输入流相同的编解码器 -an 不处理音频
47+
48+
------------------------------------------------------------------------
49+
50+
----------------------------------------------------------------------------------------------------------
51+
52+
------------------------------------------------------------------------
53+
54+
0.压缩转码mp4文件
55+
56+
ffmpeg -i input.avi -s 640x480 output.avi
57+
58+
ffmpeg -i input.avi -s vga output.avi
59+
60+
 
61+
62+
1、将文件当做直播送至live
63+
64+
ffmpeg -re -i localFile.mp4 -c copy -f flv rtmp://server/live/streamName
65+
66+
2、将直播媒体保存至本地文件
67+
68+
 
69+
70+
ffmpeg -i rtmp://server/live/streamName -c copy dump.flv
71+
72+
3、将其中一个直播流,视频改用h264压缩,音频不变,送至另外一个直播服务流
73+
74+
 
75+
76+
ffmpeg -i rtmp://server/live/originalStream -c:a copy -c:v libx264 -vpre slow -f flv rtmp://server/live/h264Stream
77+
78+
 
79+
80+
4、将其中一个直播流,视频改用h264压缩,音频改用faac压缩,送至另外一个直播服务流
81+
82+
ffmpeg -i rtmp://server/live/originalStream -c:a libfaac -ar 44100 -ab 48k -c:v libx264 -vpre slow -vpre baseline -f flv rtmp://server/live/h264Stream
83+
84+
5、将其中一个直播流,视频不变,音频改用faac压缩,送至另外一个直播服务流
85+
86+
ffmpeg -i rtmp://server/live/originalStream -acodec libfaac -ar 44100 -ab 48k -vcodec copy -f flv rtmp://server/live/h264_AAC_Stream
87+
88+
6、将一个高清流,复制为几个不同视频清晰度的流重新发布,其中音频不变
89+
90+
ffmpeg -re -i rtmp://server/live/high_FMLE_stream -acodec copy -vcodec x264lib -s 640×360 -b 500k -vpre medium -vpre baseline rtmp://server/live/baseline_500k -acodec copy -vcodec x264lib -s 480×272 -b 300k -vpre medium -vpre baseline rtmp://server/live/baseline_300k -acodec copy -vcodec x264lib -s 320×200 -b 150k -vpre medium -vpre baseline rtmp://server/live/baseline_150k -acodec libfaac -vn -ab 48k rtmp://server/live/audio_only_AAC_48k
91+
92+
7、功能一样,只是采用-x264opts选项
93+
94+
ffmpeg -re -i rtmp://server/live/high_FMLE_stream -c:a copy -c:v x264lib -s 640×360 -x264opts bitrate=500:profile=baseline:preset=slow rtmp://server/live/baseline_500k -c:a copy -c:v x264lib -s 480×272 -x264opts bitrate=300:profile=baseline:preset=slow rtmp://server/live/baseline_300k -c:a copy -c:v x264lib -s 320×200 -x264opts bitrate=150:profile=baseline:preset=slow rtmp://server/live/baseline_150k -c:a libfaac -vn -b:a 48k rtmp://server/live/audio_only_AAC_48k
95+
96+
8、将当前摄像头及音频通过DSSHOW采集,视频h264、音频faac压缩后发布
97+
98+
ffmpeg -r 25 -f dshow -s 640×480 -i video=”video source name”:audio=”audio source name” -vcodec libx264 -b 600k -vpre slow -acodec libfaac -ab 128k -f flv rtmp://server/application/stream_name
99+
100+
9、将一个JPG图片经过h264压缩循环输出为mp4视频
101+
102+
ffmpeg.exe -i INPUT.jpg -an -vcodec libx264 -coder 1 -flags +loop -cmp +chroma -subq 10 -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -flags2 +dct8x8 -trellis 2 -partitions +parti8x8+parti4x4 -crf 24 -threads 0 -r 25 -g 25 -y OUTPUT.mp4
103+
104+
10、将普通流视频改用h264压缩,音频不变,送至高清流服务(新版本FMS live=1)
105+
106+
ffmpeg -i rtmp://server/live/originalStream -c:a copy -c:v libx264 -vpre slow -f flv “rtmp://server/live/h264Stream live=1〃
107+
108+
109+
------------------------------------------------------------------------
110+
111+
----------------------------------------------------------------------------------------------------------
112+
113+
------------------------------------------------------------------------
114+
115+
 
116+
117+
1.采集usb摄像头视频命令:
118+
119+
ffmpeg -t 20 -f vfwcap -i 0 -r 8 -f mp4 cap1111.mp4
120+
121+
 
122+
123+
./ffmpeg -t 10 -f vfwcap -i 0 -r 8 -f mp4 cap.mp4
124+
125+
具体说明如下:我们采集10秒,采集设备为vfwcap类型设备,第0个vfwcap采集设备(如果系统有多个vfw的视频采集设备,可以通过-i num来选择),每秒8帧,输出方式为文件,格式为mp4。
126+
127+
 
128+
129+
2.最简单的抓屏:
130+
131+
ffmpeg -f gdigrab -i desktop out.mpg 
132+
133+
 
134+
135+
3.从屏幕的(10,20)点处开始,抓取640x480的屏幕,设定帧率为5 :
136+
137+
ffmpeg -f gdigrab -framerate 5 -offset_x 10 -offset_y 20 -video_size 640x480 -i desktop out.mpg 
138+
139+
 
140+
141+
4.ffmpeg从视频中生成gif图片:
142+
143+
ffmpeg -i capx.mp4 -t 10 -s 320x240 -pix_fmt rgb24 jidu1.gif
144+
145+
146+
### ffplay
147+
ffplay是以FFmpeg框架未基础,外加渲染音视频的库libSDL构建的媒体文件播放器。
148+
149+
ffplay [选项] [输入文件]
150+
151+
```
152+
ffplay /Users/xxx/Desktop/111.mp4
153+
ffplay http://219.151.31.38/liveplay-kk.rtxapp.com/live/program/live/hnwshd/4000000/mnf.m3u8
154+
```
155+
如果按s键就可以进入frame-step模式,即按s键一次就会播放下一帧图像。
156+
157+
##### 主要选项
158+
159+
- '-x width' 强制以 "width" 宽度显示
160+
- '-y height' 强制以 "height" 高度显示
161+
- '-an' 禁止音频
162+
- '-vn' 禁止视频
163+
- '-ss pos' 跳转到指定的位置(秒)
164+
- '-t duration' 播放 "duration" 秒音/视频
165+
- '-bytes' 按字节跳转
166+
- '-nodisp' 禁止图像显示(只输出音频)
167+
- '-f fmt' 强制使用 "fmt" 格式
168+
- '-window_title title' 设置窗口标题(默认为输入文件名)
169+
- '-loop number' 循环播放 "number" 次(0将一直循环)
170+
- '-showmode mode' 设置显示模式
171+
- 可选的 mode :
172+
- '0, video' 显示视频
173+
- '1, waves' 显示音频波形
174+
- '2, rdft' 显示音频频带
175+
- 默认值为 'video',你可以在播放进行时,按 "w" 键在这几种模式间切换
176+
- '-i input_file' 指定输入文件
177+
- '-sync type' 设置主时钟为音频、视频、或者外部。默认为音频。主时钟用来进行音视频同步
178+
- '-threads count' 设置线程个数
179+
- '-autoexit' 播放完成后自动退出
180+
- '-exitonkeydown' 任意键按下时退出
181+
- '-exitonmousedown' 任意鼠标按键按下时退出
182+
- '-acodec codec_name' 强制指定音频解码器为 "codec_name"
183+
- '-vcodec codec_name' 强制指定视频解码器为 "codec_name"
184+
- '-scodec codec_name' 强制指定字幕解码器为 "codec_name"
185+
186+
如果希望从视频的第30秒开始播放,播放10秒钟的文件,则可以使用如下命令
187+
`ffplay -ss 30 -t 10 /Users/xxx/Desktop/111.mp4`
188+
189+
##### 音画同步
190+
191+
ffplay也是一个视频播放器,所以不得不提出来的一个问题是:音画同步。
192+
ffplay的音画同步的实现方式其实有三种,分别是:
193+
- 以音频为主时间轴作为同步源
194+
- 以视频为主时间轴作为同步源
195+
- 以外部时钟为主时间轴作为同步源。
196+
197+
下面就以音频为主时间轴来作为同步源来作为案例进行讲解,而且ffplay默认也是以音频为基准进行对齐的,那么以音频作为对齐基准是如何实现的呢?
198+
199+
首先需要说明的是,播放器接收到的视频帧或者音频帧,内部都是会有时间戳(PTS时钟)来标识它实际应该在什么时刻展示,实际的对齐策略如下:
200+
比较视频当前的播放时间和音频当前的播放时间,如果视频播放过快,则通过加大延迟或者重复播放来降低视频播放速度,如果视频播放慢了,则通过减小延迟或者丢帧来追赶音频播放的时间点。
201+
关键就在于音视频时间的比较和延迟的计算,当前在比较的过程中会设置一个阈值,如果超过预设的阈值就应该作出调整(丢帧或者重复渲染),这就是整个对齐策略。
202+
203+
在使用ffplay的时候,我们可以明确的指定使用那种对齐方式,比如:
204+
`ffplay test.mp4 -sync audio`
205+
上面这个命令显式的指定了使用以音频为基准进行音视频同步的方式播放视频文件,当然这也是ffplay的默认播放设置。
206+
`ffplay test.mp4 -sync video`
207+
上面这个命令显式的指定了使用以视频为基准进行音视频同步的方式播放视频文件。
208+
`ffplay test.mp4 -sync ext`
209+
上面这个命令显式的指定了使用外部时钟为基准进行音视频同步的方式播放视频文件。
210+
211+
212+
### ffprobe
213+
ffprobe是ffmpeg命令行中用来查看媒体文件格式的工具。
214+
215+
命令格式:
216+
`ffprobe [文件名]`
217+
218+
```
219+
ffprobe /Users/xxx/Desktop/111.mp4
220+
221+
ffprobe version 4.4 Copyright (c) 2007-2021 the FFmpeg developers
222+
built with Apple clang version 12.0.5 (clang-1205.0.22.9)
223+
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.4_2 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-avresample --enable-videotoolbox
224+
libavutil 56. 70.100 / 56. 70.100
225+
libavcodec 58.134.100 / 58.134.100
226+
libavformat 58. 76.100 / 58. 76.100
227+
libavdevice 58. 13.100 / 58. 13.100
228+
libavfilter 7.110.100 / 7.110.100
229+
libavresample 4. 0. 0 / 4. 0. 0
230+
libswscale 5. 9.100 / 5. 9.100
231+
libswresample 3. 9.100 / 3. 9.100
232+
libpostproc 55. 9.100 / 55. 9.100
233+
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/xuchuanren/Desktop/111.mp4':
234+
Metadata:
235+
major_brand : isom
236+
minor_version : 512
237+
compatible_brands: isomiso2avc1mp41
238+
encoder : Multimedia Cloud Transcode (cloud.baidu.com)
239+
comment : Content Adaptive Encoding 3.0
240+
Duration: 00:00:41.52, start: 0.000000, bitrate: 163 kb/s // 视频的时长是41秒52毫秒,开始播放时间是0,,整个文件的比特率是163Kbit/s
241+
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 91 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
242+
// 上面这一行的信息是,第一个流是视频流,编码格式是h264格式(封装格式是AVC1),每一帧的数据表示为yuv420p,分辨率为1280*720.这路流的比特率为91Kbit/s,帧率为每秒钟25帧
243+
Metadata:
244+
handler_name : VideoHandler
245+
vendor_id : [0][0][0][0]
246+
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 65 kb/s (default)
247+
// 上面这一行的信息是,第二个流为音频流,编码方式为ACC(封装格式为MP4A),并且采用的Profile是LC规格,采样率是44.1KHz,声道是立体声,这路流的比特率是65Kbit/s
248+
Metadata:
249+
handler_name : SoundHandler
250+
vendor_id : [0][0][0][0]
251+
```
252+
253+
查看流的格式信息
254+
ffprobe -show_format -i /Users/xxx/Desktop/111.mp4
255+
256+
```
257+
[FORMAT]
258+
filename=/Users/xxx/Desktop/111.mp4
259+
nb_streams=2
260+
nb_programs=0
261+
format_name=mov,mp4,m4a,3gp,3g2,mj2
262+
format_long_name=QuickTime / MOV
263+
start_time=0.000000
264+
duration=41.518000
265+
size=848895
266+
bit_rate=163571
267+
probe_score=100
268+
TAG:major_brand=isom
269+
TAG:minor_version=512
270+
TAG:compatible_brands=isomiso2avc1mp41
271+
TAG:encoder=Multimedia Cloud Transcode (cloud.baidu.com)
272+
TAG:comment=Content Adaptive Encoding 3.0
273+
[/FORMAT]
274+
```
275+
查看每一帧信息
276+
ffprobe -show_frames -i /Users/xxx/Desktop/111.mp4
277+
278+
查看包信息
279+
ffprobe -show_packets -i /Users/xxx/Desktop/111.mp4
280+
281+
282+
283+
---
284+
285+
- 邮箱 :charon.chui@gmail.com
286+
- Good Luck!
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
FFmpeg简介
2+
===
3+
4+
FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。
5+
6+
主要的开发库:
7+
8+
- libavutil:包含一些公共的工具函数,包括随机数生成、数据结构、核心多媒体工具等;
9+
- libavcodec:用于各种类型声音/图像encode/decode编解码库;
10+
- libavformat:用于各种音视频封装格式(mp4/AVI/Flv等)的生成和解析muxer/demuxer,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;
11+
- libavdevice:读取电脑(或者其他设备上)的多媒体设备的数据 或者输出数据到指定的多媒体设备上;
12+
- libswresample: 用于音频采样采样数据(PCM)转换的库;
13+
- libswscale:用于视频场景比例缩放、色彩映射转换的库;
14+
- libavfilter: 包含媒体滤波器的库
15+
16+
主要的工具集:
17+
18+
- ffmpeg:一个命令行工具,可用于格式转换、解码、编码等;
19+
- ffsever:一个 HTTP 、RTSP的实时广播流媒体服务器;
20+
- ffplay:是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示;
21+
- ffprobe : 一个多媒体流分析工具。 它从多媒体流中收集信息 并且以人类和机器可读的形式打印出来。
22+
23+
24+
---
25+
26+
- 邮箱 :charon.chui@gmail.com
27+
- Good Luck!

0 commit comments

Comments
 (0)