ffmpeg与ffserver的协同工作
ffmpeg和ffserver配合使用可以实现实时的流媒体服务,可以实时传输来自摄像头的数据,客户端可以采用HTTP、RTSP、RTP协议等播放视频流。
一、概念和流程
ffmpeg和ffserver配合使用涉及到四个概念:
1. ffmpeg,负责媒体文件的转码工作,把你服务器上的源媒体文件转换成要发送出去的流媒体文件。
2. ffserver,负责响应客户端的流媒体请求,把流媒体数据发送给客户端。
3. ffserver.conf,ffserver启动时的配置文件,在这个文件中主要是对网络协议,缓存文件feed1.ffm和要发送的流媒体文件的格式参数做具体的设定。
4. feed1.ffm,可以看成是一个流媒体数据的缓存文件,ffmpeg把转码好的数据发送给ffserver,如果没有客户端连接请求,ffserver把数据缓存到该文件中。
工作流程如下:
1、 启动ffserver,配置参数
ffserver先于ffmpeg启动,它在启动的时候需要加参数-f指定其配置文件,配置文件里包含端口信息、缓冲文件配置、传送流配置(如编码方式,帧率,采样率……)。
2、 启动ffmpeg,输入流
启动ffmpeg,向缓冲文件输入数据流,数据流可以来自摄像头,也可以来自本来就存在的文件。
feed1.ffm是一个缓冲文件,fserver启动后,feed1.ffm就会自动被创建,feed1.ffm开始的部分已经写入向客户端传送流的配置信息,在feed1.ffm做缓冲用的时候,这些信息是不会被覆盖掉。
ffmpeg启动的一个关键参数就是“http://ip:port/feed1.ffm”,其中ip是运行ffserver主机的ip,如果ffmpeg和ffserver都在同一系统中运行的话,用localhost或者127.0.0.1也行。ffmpeg启动后会与ffserver建立一个连接(短暂的连接),通过这第一次的连接,ffmpeg从ffserver那里获取了向客户端输出流的配置,并把这些配置作为自己编码输出的配置,然后ffmpeg断开了这次连接,再次与ffserver建立连接(长久的连接),利用这个连接ffmpeg会把编码后的数据发送给ffserver。如果你观察ffserver端的输出就会发现这段时间会出现两次HTTP的200,这就是两次连接的过程。
3、连接过程
ffmpeg从摄像头获取数据后,按照输出流的编码方式编码,然后发送给ffserver,ffserver收到ffmpeg的数据后,如果网络上没有播放的请求,就把数据写入feed1.ffm中缓存,写入时把数据加上些头信息然后分块,每块4096B(每块也有结构),当feed1.ffm的大小到了ffserver.conf中规定的大小后,就会从文件开始(跳过头)写入,覆盖旧的数据。直到网络上有播放的请求,ffserver从feed1.ffm中读取数据,发送给客户端。
二、配置与应用
ffserver可以配置为带缓冲或者不带缓冲,其中不带缓冲的只需要配置stream的位置,不需要feed和ffmpeg。
ffserver配置文件可以参考ffmpeg源码中的doc/ffserver.conf,里边有详细的注释。文件的结构可以分为头部信息、实时流信息、格式信息。
1、不带缓冲
最简单的配置文件如下
Port 9999
RTSPPort9990
BindAddress0.0.0.0
MaxClients1000
MaxBandwidth100000
CustomLog–
#只需要指定待播放的文件的路径以及格式信息即可
<Stream test.flv>
File "/home/test.flv"
Format flv
</Stream>
#rtsp应用
<Stream test.mpg>
File"myfile/testvideo/test.mpg"
Format rtp
</Stream>
命令符:
1. 在终端里输入ffserver -f /etc/ffserver.conf
2. 在浏览器里或者相关播放器地址里输入 http://ipAddr:port/test.flv
备注:1、Port为配置里面的9999,文件名直接输入流的文件名即可。
2、实际测试flv等格式都可以播放。
3、测试需要的test.flv的可以使用ffmpeg录制,命令是
ffmpeg -f v4l2 -s 320*240 -r 10 -i /dev/video2-vcodec flv /test.flv
2、带缓冲
配置文件如下
Port 9999
RTSPPort9990
BindAddress0.0.0.0
MaxClients1000
MaxBandwidth10000
CustomLog–
<Feed feed1.ffm>
File/tmp/feed1.ffm
FileMaxSize40k
ACL allow127.0.0.1
</Feed>
<Stream test.flv>
Feed feed1.ffm
Format flv
BitExact
DctFastint
IdctSimple
VideoFrameRate10
VideoSize320x240
VideoBitRate64
VideoGopSize10
NoAudio
PreRoll10
StartSendOnKey
MaxTime100
</Stream>
要点:
1、实时流数据配置,其中注意文件的位置,可以放到tmp文件夹下面,这样会被自动清理掉。
2、每个不同的流都来自feed1.ffm,因此配置越多的流,当执行的时候,会逐个转换,影响速度,一般不建议多配置。
3、ACL allow表示ip的地址范围,比如ACL allow 192.168.0.0 192.168.255.255
命令符:
1. 在终端里输入
ffserver -f/etc/ffserver.conf
2. a.若是文件方式则输入
ffmpeg -i/home/test.flv http://127.0.0.1:9999/test.flv
b.若是实时视频则输入
ffmpeg -fv4l2 -framerate 30 -i /dev/video2http://127.0.0.1:9999/feed1.ffm
3、运行客户端命令
http://10.30.30.117:9999/test.flv
rtsp://ip:port/rtsp.mpg
三、流的格式
文件的拓展名对应一定的格式,常用的有:
拓展名 | 格式 |
flv | flv |
mp4 | mp4 |
mpg | rtp |
| libx264 |
.asf | asf |
.mjpg | mjpg |
.jpg | jpeg |
配置例子:
Multipart JPEG
| <Stream test.mjpg> Feed feed1.ffm Format mpjpeg VideoFrameRate 2 VideoIntraOnly NoAudio Strict -1 </Stream> |
Single JPEG
| <Stream test.jpg> Feed feed1.ffm Format jpeg VideoFrameRate 2 VideoIntraOnly VideoSize 352x240 NoAudio Strict -1 </Stream> |
Flash
| <Stream test.swf> Feed feed1.ffm Format swf VideoFrameRate 2 VideoIntraOnly NoAudio </Stream> |
ASF compatible
| <Stream test.asf> Feed feed1.ffm Format asf VideoFrameRate 15 VideoSize 352x240 VideoBitRate 256 VideoBufferSize 40 VideoGopSize 30 AudioBitRate 64 StartSendOnKey </Stream> |
MP3 audio
| <Stream test.mp3> Feed feed1.ffm Format mp2 AudioCodec mp3 AudioBitRate 64 AudioChannels 1 AudioSampleRate 44100 NoVideo </Stream> |
Ogg Vorbis audio
| <Stream test.ogg> Feed feed1.ffm Metadata title "Stream title" AudioBitRate 64 AudioChannels 2 AudioSampleRate 44100 NoVideo </Stream> |
Real with audio only at 32 kbits
| <Stream test.ra> Feed feed1.ffm Format rm AudioBitRate 32 NoVideo </Stream> |
Real with audio and video at 64 kbits
| <Stream test.rm> Feed feed1.ffm Format rm AudioBitRate 32 VideoBitRate 128 VideoFrameRate 25 VideoGopSize 25 </Stream> |
For stream coming from a file: you onlyneed to set the input filename and optionally a new format.
| <Stream file.rm> File "/usr/local/httpd/htdocs/tlive.rm" NoAudio </Stream> |
| <Stream file.asf> File "/usr/local/httpd/htdocs/test.asf" NoAudio Metadata author "Me" Metadata copyright "Super MegaCorp" Metadata title "Test stream from disk" Metadata comment "Test comment" </Stream> |
实测可行的例子
配置:
<Streammy.mp4>
Formatrtp
File"/home/my.mp4"
</Stream>
客户端命令 rtsp://192.168.1.230:9990/my.mp4
端口就是rtp的端口。使用http协议不能访问。
<Streamtest.mp4>
Feedfeed1.ffm
Formatrtp
BitExact
DctFastint
IdctSimple
VideoFrameRate10
VideoSize320x240
VideoBitRate64
VideoGopSize10
NoAudio
PreRoll10
StartSendOnKey
MaxTime100
</Stream>
ffmpeg -fv4l2 -r 10 -I /dev/video2 http://127.0.0.1:9999/feed1.ffm
客户端命令 rtsp://192.168.1.230:9990/test.mp4
<Streamlive.h264>
Formatrtp
Feedfeed1.ffm
VideoCodeclibx264
VideoFrameRate24
VideoBitRate100
VideoSize480x272
AVPresetVideodefault
AVPresetVideobaseline
AVOptionVideoflags +global_header
AudioCodeclibfaac
AudioBitRate32
AudioChannels2
AudioSampleRate22050
AVOptionAudioflags +global_header
</Stream>
使用H.264编码时,使用命令
ffmpeg -f v4l2 -s 176*144 -r 2 -i /dev/video0-vcodec libx264 http://192.168.1.6:8090/feed1.ffm
ffmpeg-f v4l2 -s 176*144 -r 2 -vpre libx264-hq.ffpreset -i /dev/video0 -vcodeclibx264http://localhost:8090/feed1.ffm
ffmpeg-f v4l2 -s 176*144 -r 10 -vpre libx264-hq.ffpreset-i /dev/video0 -vcodec libx264 -f rtprtp://192.168.1.105:6060 > /tmp/x264.sdp
四、协议
HTTP协议的地址格式为:
http://ffserver_ip_address:http_port/stream_name[options]
RTSP协议的地址格式为:
http://ffserver_ip_address:rtsp_port/stream_name[options]
Sampleffserver configuration file
Port 8090
BindAddress 0.0.0.0
MaxHTTPConnections 2000
MaxClients 1000
MaxBandwidth 1000
CustomLog -
##################################################################
<Feed feed1.ffm>
# ffmpeg http://localhost:8090/feed1.ffm
File /tmp/feed1.ffm
FileMaxSize 200K
ACL allow 127.0.0.1
</Feed>
##################################################################
<Stream test1.mpg>
Feed feed1.ffm
# Format of the stream : you can choose among:
# mpeg : MPEG-1 multiplexed video and audio
# mpegvideo : only MPEG-1 video
# mp2 : MPEG-2 audio (use AudioCodec to select layer 2 and 3 codec)
# ogg : Ogg format (Vorbis audio codec)
# rm : RealNetworks-compatible stream. Multiplexed audio and video.
# ra : RealNetworks-compatible stream. Audio only.
# mpjpeg : Multipart JPEG (works with Netscape without any plugin)
# jpeg : Generate a single JPEG image.
# asf : ASF compatible streaming (Windows Media Player format).
# swf : Macromedia Flash compatible stream
# avi : AVI format (MPEG-4 video, MPEG audio sound)
Format mpeg
# Bitrate for the audio stream. Codecs usually support only a few
# different bitrates.
AudioBitRate 32
# Number of audio channels: 1 = mono, 2 = stereo
AudioChannels 1
# Sampling frequency for audio. When using low bitrates, you should
# lower this frequency to 22050 or 11025. The supported frequencies
# depend on the selected audio codec.
AudioSampleRate 44100
# Bitrate for the video stream
VideoBitRate 64
# Ratecontrol buffer size
VideoBufferSize 40
# Number of frames per second
VideoFrameRate 3
# Size of the video frame: WxH (default: 160x128)
# The following abbreviations are defined: sqcif, qcif, cif, 4cif, qqvga,
# qvga, vga, svga, xga, uxga, qxga, sxga, qsxga, hsxga, wvga, wxga, wsxga,
# wuxga, woxga, wqsxga, wquxga, whsxga, whuxga, cga, ega, hd480, hd720,
# hd1080
VideoSize 160x128
# Transmit only intra frames (useful for low bitrates, but kills frame rate).
#VideoIntraOnly
# If non-intra only, an intra frame is transmitted every VideoGopSize
# frames. Video synchronization can only begin at an intra frame.
VideoGopSize 12
# More MPEG-4 parameters
# VideoHighQuality
# Video4MotionVector
# Choose your codecs:
#AudioCodec mp2
#VideoCodec mpeg1video
# Suppress audio
#NoAudio
# Suppress video
#NoVideo
#VideoQMin 3
#VideoQMax 31
# Set this to the number of seconds backwards in time to start. Note that
# most players will buffer 5-10 seconds of video, and also you need to allow
# for a keyframe to appear in the data stream.
#Preroll 15
# ACL:
# You can allow ranges of addresses (or single addresses)
#ACL ALLOW <first address>
# You can deny ranges of addresses (or single addresses)
#ACL DENY <first address>
# You can repeat the ACL allow/deny as often as you like. It is on a per
# stream basis. The first match defines the action. If there are no matches,
# then the default is the inverse of the last ACL statement.
#
# Thus 'ACL allow localhost' only allows access from localhost.
# 'ACL deny 1.0.0.0 1.255.255.255' would deny the whole of network 1 and
# allow everybody else.
</Stream>
##################################################################
# Example streams
# Multipart JPEG
#<Stream test.mjpg>
#Feed feed1.ffm
#Format mpjpeg
#VideoFrameRate 2
#VideoIntraOnly
#NoAudio
#Strict -1
#</Stream>
# Single JPEG
#<Stream test.jpg>
#Feed feed1.ffm
#Format jpeg
#VideoFrameRate 2
#VideoIntraOnly
##VideoSize 352x240
#NoAudio
#Strict -1
#</Stream>
# Flash
#<Stream test.swf>
#Feed feed1.ffm
#Format swf
#VideoFrameRate 2
#VideoIntraOnly
#NoAudio
#</Stream>
# ASF compatible
<Stream test.asf>
Feed feed1.ffm
Format asf
VideoFrameRate 15
VideoSize 352x240
VideoBitRate 256
VideoBufferSize 40
VideoGopSize 30
AudioBitRate 64
StartSendOnKey
</Stream>
# MP3 audio
#<Stream test.mp3>
#Feed feed1.ffm
#Format mp2
#AudioCodec mp3
#AudioBitRate 64
#AudioChannels 1
#AudioSampleRate 44100
#NoVideo
#</Stream> # Ogg Vorbis audio
#<Stream test.ogg>
#Feed feed1.ffm
#Title "Stream title"
#AudioBitRate 64
#AudioChannels 2
#AudioSampleRate 44100
#NoVideo
#</Stream>
# Real with audio only at 32 kbits
#<Stream test.ra>
#Feed feed1.ffm
#Format rm
#AudioBitRate 32
#NoVideo
#NoAudio
#</Stream> # Real with audio and video at 64 kbits
#<Stream test.rm>
#Feed feed1.ffm
#Format rm
#AudioBitRate 32
#VideoBitRate 128
#VideoFrameRate 25
#VideoGopSize 25
#NoAudio
#</Stream>
##################################################################
# A stream coming from a file: you only need to set the input
# filename and optionally a new format. Supported conversions:
# AVI -> ASF
#<Stream file.rm>
#File "/usr/local/httpd/htdocs/tlive.rm"
#NoAudio
#</Stream>
#<Stream file.asf>
#File "/usr/local/httpd/htdocs/test.asf"
#NoAudio
#Author "Me" #Copyright "Super MegaCorp" #Title "Test stream from disk" #Comment "Test comment" #</Stream> ################################################################## # RTSP examples # # You can access this stream with the RTSP URL: # rtsp://localhost:5454/test1-rtsp.mp # # A non-standard RTSP redirector is also created. Its URL is: # http://localhost:8090/test1-rtsp.rtsp #<Stream test1-rtsp.mpg> #Format rtp #File "/usr/local/httpd/htdocs/test1.mpg" #</Stream> # Transcode an incoming live feed to another live feed, # using libx264 and video presets #<Stream live.h264> #Format rtp #Feed feed1.ffm #VideoCodec libx264 #VideoFrameRate 24 #VideoBitRate 100 #VideoSize 480x272 #AVPresetVideo default #AVPresetVideo baseline #AVOptionVideo flags +global_header # #AudioCodec libfaac #AudioBitRate 32 #AudioChannels 2 #AudioSampleRate 22050 #AVOptionAudio flags +global_header #</Stream> ################################################################## # SDP/multicast examples # # If you want to send your stream in multicast, you must set the # multicast address with MulticastAddress. The port and the TTL can # also be set. # # An SDP file is automatically generated by ffserver by adding the # 'sdp' extension to the stream name (here # http://localhost:8090/test1-sdp.sdp). You should usually give this # file to your player to play the stream. # # The 'NoLoop' option can be used to avoid looping when the stream is # terminated. #<Stream test1-sdp.mpg> #Format rtp #File "/usr/local/httpd/htdocs/test1.mpg" #MulticastAddress 224.124.0.1 #MulticastPort 5000 #MulticastTTL 16 #NoLoop #</Stream> ################################################################## # Special streams # Server status <Stream stat.html> Format status # Only allow local people to get the status ACL allow localhost ACL allow 192.168.0.0 192.168.255.255 #FaviconURL http://pond1.gladstonefamily.net:8080/favicon.ico </Stream> # Redirect index.html to the appropriate site <Redirect index.html> URL http://www.ffmpeg.org/ </Redirect>
===============================================================
[/etc/ffserver.conf]
HTTPPort 8090
HTTPBindAddress 0.0.0.0
MaxHTTPConnections 2000
MaxClients 1000
MaxBandwidth 40000
CustomLog -
UseDefaults
<Feed feed1.ffm>
File /tmp/feed1.ffm
FileMaxSize 5M
ACL allow localhost
</Feed>
<Stream flv>
Feed feed1.ffm
Format flv
VideoFrameRate 40
VideoBitRate 128
VideoSize 1920x1080
AVOptionVideo flags +global_header
AudioBitRate 24
AudioChannels 2
AudioSampleRate 44100
AVOptionAudio flags +global_header
</Stream>
<Stream mp4>
Feed feed1.ffm
Format mp4
VideoFrameRate 40
VideoBitRate 128
VideoSize 1920x1080
AVOptionVideo flags +global_header
AudioBitRate 24
AudioChannels 2
AudioSampleRate 44100
AVOptionAudio flags +global_header
</Stream>
<Stream avi>
Feed feed1.ffm
Format avi
VideoFrameRate 40
VideoBitRate 128
VideoSize 1920x1080
AVOptionVideo flags +global_header
AudioBitRate 24
AudioChannels 2
AudioSampleRate 44100
AVOptionAudio flags +global_header
</Stream>
启动服务:ffserver -d -f /etc/ffserver.conf
推流:ffmpeg -i MY_RTP_SOURCE http://localhost:8090/feed1.ffm
客户端使用:
<head>
<link href="http://vjs.zencdn.net/c/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/c/video.js"></script>
</head>
<body>
<video id="video1" class="video-js vjs-default-skin" width="640" height="360"
data-setup='{"controls" : true, "autoplay" : true, "preload" : "auto"}'>
<source src="http://10.10.3.108:8090/stream" type="video/x-flv">
</video>
</body>
首先是推流的指令
ffmpeg -re -i filename -r 40 -ss 0 -t 10 -c copy -f flv url
使用-re是限制ffmpeg的上传帧率,如果在使用ffmpeg推流的时候一定要添加-re的选项,否则ffmpeg会按照自身能力进行最大帧率的上传,就会导致流媒体服务器处理能力受限或者拉流端处理能力有限导致各类问题
使用-i是必须有的,后面接要上传的文件名字
使用-r是显式设置上传帧率,在使用-re的情况下默认25
使用-ss是设置从文件的哪个时间点开始上传,支持hh:mm:ss的格式
使用-t是设置上传文件的时间长度
使用-c表示音频视频编码格式保持不变,不进行转码(也可以分别携程-acodec -vcodec 后面接着要编码的形式或者copy)
使用-f表示上传时使用的文件封装格式,一般流媒体服务使用flv格式进行
最后一个url表示上传的流媒体服务器地址
接着是拉流的指令
ffmpeg -i url -c copy -f flv filename
ffmpeg -i rtmp://server/live/stramName -c copy dump.flv
ffmpeg -i http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8 -c copy dump.m3u8
拉流的指令就比较简单,同样也可以使用-ss -t等参数
需要注意的一点是,-ss既可以放在-i之前,也可以放在文件名的后面,但是建议放在文件名的后面,这样会加快文件读取速度