在网页上实现任意格式的音视频快速播放功能的开发总结。

开发重点在pc端,手机端不考虑。

要实现用户上传音视频到服务器,上传完毕即可随意拖动进度条观看。

h5自带的video标签不支持大多数格式的音视频格式,不考虑。

考虑使用流媒体播放,把源视频转成视频流推到网页播放器。

使用nginx+nginx-rtmp-module+ffmpeg搭建了个流媒体服务器,使用rtmp和hls两种推流方式做实验,用vlc进行播放并成功,但是发现这是直播,没有进度,空欢喜一场,不过也了解了直播功能的实现。此方案行不通,舍弃。

hls流媒体方式,是一个m3u8文件,里面是一个个的视频片段文件列表,一堆ts格式的小文件,所以想用这种方式来实现。


用ffmpeg进行视频的m3u8自动分段,会生成一个m3u8文件和一堆ts文件。

命令: ffmpeg -i 文件名  -c:v libx264 -c:a aac -hls_time 10 -hls_list_size 0  -strict -2 -f hls output.m3u8

-c:v -c:a:分别是视频音频的编码类型

-hls_time n: 设置每片的长度,默认值为2。单位为秒

-hls_list_size n:设置播放列表保存的最多条目,设置为0会保存有所片信息,默认值为5

-hls_wrap n:设置多少片之后开始覆盖,如果设置为0则不会覆盖,默认值为0.这个选项能够避免在磁盘上存储过多的
片,而且能够限制写入磁盘的最多的片的数量
-hls_start_number n:设置播放列表中sequence number的值为number,默认值为0


首先,生成好了文件,要想办法能在网页上进行播放,试了好几款播放器,最后用了ckplayer,官方帮助文档里有如何播放m3u8流媒体的方法,原理是使用flash进行播放,一个swf播放器。播放器先请求m3u8文件,根据文件列表中的时长算出该视频的总进度。拖动进度时请求相应的ts文件。一系列的请求都是由播放器发出的。

尝试获取播放器的请求,使用django创建一个工程,设置一个静态文件夹,把生成好的视频文件放进去,网页上写好m3u8文件路径,就可以正常播放了,但是无法监听播放器请求。所以就把视频文件放到普通文件夹,根据播放器的请求链接,设置一个url对应后台一个方法,每次请求都会走这个方法,可以获取到请求的是哪个文件,请求哪个文件,我就找到此文件,以流的方式打开(open(tsfilepath, 'rb'))并返回,成功播放。

实现任意进度播放,就要根据所请求的文件,计算出该文件是从源文件第几秒开始,从此处往后截取视频片段返回就可以了。

关键代码如下:

先生成一个临时文件

os.system("ffmpeg -i %s -ss %d -t %d  -c:v libx264 -c:a aac -g 5 -sc_threshold 0 %s" % (源文件路径, 第几个ts文件* 每段多长, 每段多长, 生成ts路径))
设置此文件的start_time才能正常播放,具体原理不是很清楚。
os.system("ffmpeg -i %s/%s -ss %d -t %d  -c:v copy -c:a copy -g 5 -sc_threshold 0 %s/%s" % (tsdirpath, tsname, -tsnum * cuttime, cuttime * (tsnum + 1), tsdirpath,  tsfile))
os.system("rm -f %s/%s" % (tsdirpath, tsname))

-ss 开始时间

-t开始时间后的几秒,也就是这个片段的长度

视频截取时-i 和 -ss的前后位置影响很大。

-i在前是根据关键帧进行查找,速度快。

-i在后是逐帧查找,速度非常慢,精度高,适合小文件。

详情见:http://trac.ffmpeg.org/wiki/Seeking点击打开链接

总结:

1、手动生成m3u8文件,需要获取文件总时长,设置每个片段长度。
 filemsg = os.popen("ffprobe -v error -show_entries format=duration -print_format json %s" % srcvideopath).read()
print(filemsg)
length = float(json.loads(filemsg)['format']['duration'])

2、根据请求生成对应ts文件并返回。

你可能感兴趣的:(Python)