使用FFmpeg推流实现在B站24小时点歌直播
本文首发于个人博客
安装FFmpeg
centos7
https://www.myfreax.com/how-to-install-ffmpeg-on-centos-7/
https://linuxize.com/post/how-to-install-ffmpeg-on-centos-7/
使用FFmpeg在B站直播
https://zhuanlan.zhihu.com/p/23951969
实现一个点歌台在B站24小时直播
下图是使用FFmpeg推流到B站,实现24小时直播歌曲的截图
体验地址👉https://live.bilibili.com/23752609
想法主要参考了👉https://github.com/chenxuuu/24h-raspberry-live-on-bilibili
FFmpeg推流
因为直播的话推的是视频,所以要想办法把音频文件 + 图片 + 字幕 合成视频
使用一张图片生成视频
shell
ffmpeg -loop 1 -i 1.jpg -t 5 1.flv
-loop 1
:表示对输入的图片流进行循环-i 1.jpg
:表示1.jpg这张图片作为输入-t 5
: 表示输出视频是5s1.flv
:表示最后生成的视频的名称叫1.flv
这样就生成了一个5s视频,当然了是没有声音的
给视频加上音频
在上一步的基础上加上一个mp3格式的音频-i 1.mp3
,就可以合成一个5s带有音频的视频
shell
ffmpeg -loop 1 -i 1.jpg -i 1.mp3 -t 5 1.flv
给视频加上ASS字幕
shell
ffmpeg -loop 1 -i 1.jpg -i 1.mp3 -vf "ass=x.ass" -t 5 1.flv
这样就可以给视频加上字幕了
参考官方文档👉https://trac.ffmpeg.org/wiki/HowToBurnSubtitlesIntoVideo
推流
推流只需要将最后的1.flv换成推流地址就好了
shell
ffmpeg -loop 1 -i 1.jpg -i 1.mp3 -vf "ass=x.ass" -t 5 rtmp://live-push.bilivideo.com/live-bvc/?streamname=xxxx&key=xxx
编解码
这样推到B站的流可能因为编码的问题在电脑浏览器上无法播放,这个时候就要对视频进行编码
shell
ffmpeg -loop 1 -i 1.jpg -i 1.mp3 -vf "ass=x.ass" -t 5 -c:v libx264 -c:a aac rtmp://live-push.bilivideo.com/live-bvc/?streamname=xxxx&key=xxx
-c:v libx264
:这里表示对视频流用libx264编码-c:a aac
:表示对音频流用aac编码
贴一个我用的命令
shell
ffmpeg -loglevel warning -threads 0 -re -loop 1 -r 20 -t 234 -f image2 -i "download/用来生成视频的图片.jpg" -filter_complex "ass=download/字幕.ass[result]" -i "download/音频.mp3" -map "[result]" -map 1,0 -preset ultrafast -crf 18 -maxrate 500k -b:v 192k -c:v libx264 -c:a aac -bufsize 2M -f flv "rtmp://live-push.bilivideo.com/live-bvc/?streamname=xxxx&key=yyy"
详细的参数介绍
-
-re (input)
:以指定帧率读取输入。通常用于模拟一个硬件设备,例如在直播输入流(这时是读取一个文件)。不应该在实际设备或者在直播输入中使用(因为这将导致数据包的丢弃)。默认ffmpeg
会尽量以最高可能的帧率读取。这个选项可以降低从输入读取的帧率,这常用于实时输出(例如直播流)。 -
-loop_input
:循环输入流。当前它仅作用于图片流。这个选项主要用于FFserver自动化测试。这个选项现在过时了,应该使用-loop 1
-
-i filename (input)
:指定输入文件 -
-r[:stream_specifier] fps (input/output,per-stream)
:设置帧率(一种Hz值,缩写或者分数值)。在作为输入选项时,会忽略文件中存储的时间戳和时间戳而产生的假设恒定帧率
fps
,即强制按设定帧率处理视频产生(快进/减缓效果)。这不像-framerate
选项是用来让一些输入文件格式如image2或者v412(兼容旧版本的FFmpeg)等,要注意这一点区别,而不要造成混淆。作为输出选项时,会复制或者丢弃输入中个别的帧以满足设定达到
fps
要求的帧率。 -
-t duration (input/output)
:限制输入/输出的时间。如果是在-i
前面,就是限定从输入中读取多少时间的数据;如果是用于限定输出文件,则表示写入多少时间数据后就停止。duration
可以是以秒为单位的数值或者hh:mm:ss[.xxx]
格式的时间值。 -
-f fmt (input/output)
:指定输入或者输出文件格式。常规可省略而使用依据扩展名的自动指定,但一些选项需要强制明确设定 -
-filter_complex filtergraph (global)
:定义一个复合滤镜,可以有任意数量的输入/输出。最简单的滤镜链图至少有一个输入和一个输出,且需要相同类型。参考-filter
以获取更多信息(更有价值)。filtergraph
用来指定一个滤镜链图。关于滤镜链图的语法
可以参考ffmpeg-filters
相关章节。其中输入链标签必须对应于一个输入流。filtergraph的具体描述可以使用
file_index:stream_specifier
语法(事实上这同于-map
)。如果stream_specifier
匹配到了一个多输出流,则第一个被使用。滤镜链图中一个未命名输入将匹配链接到的输入中第一个未使用且类型匹配的流。使用
-map
来把输出链接到指定位置上。未标记的输出会添加到第一个输出文件。这里
[0:v]
是第一个输入文件的第一个视频流,它作为滤镜的第一个(主要的)输入,同样,第二个输入文件的第一个视频流作为滤镜的第二个输入。 -
-map [-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]] | [linklabel] (output)
:设定一个或者多个输入流作为输出流的源。每个输入流是以input_file_id
序数标记的输入文件和input_stream_id
标记的流序号共同作用指明,它们都以0起始计数。如果设置了sync_file_id:stream_specifier
,则把这个输入流作为同步信号参考。 -
-pix_fmt[:stream_specifier] format (input/output,per-stream)
:设置像素格式。使用-pix_fmts
可以显示所有支持的像素格式。如果设置的像素格式不能被选中(启用),则ffmpeg会输出一个警告和并选择这个编码最好(兼容)的像素格式。如果pix_fmt
前面前导了一个+
字符,ffmepg会在要求的像素格式不被支持时退出,这也意味着滤镜中的自动转换也会被禁止。如果pix_fmt
是单独的+
,则ffmpeg选择和输入(或者滤镜通道)一样的像素格式作为输出,这时自动转换也会被禁止。 -
-preset
:指定输出的视频质量,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。 -
-c:v codec (input/output,per-stream)
:c是指codec,为特定的文件选择编/解码模式,对于输出文件就是编码器,对于输入或者某个流就是解码器。选项参数中codec
是编解码器的名字,或者是copy
(仅对输出文件)则意味着流数据直接复制而不再编码 -
-b:v (output)
:设置输出视频的码率,b应该是bate的意思
搭点歌台可能用到的
CentOS7安装中文字体,👉https://segmentfault.com/a/1190000040275198
FFmpeg使用中文文档,👉https://xdsnet.gitbooks.io/other-doc-cn-ffmpeg/content/ffmpeg-doc-cn-01.html
CentOS 7.4 安装python3及虚拟环境,👉https://zhuanlan.zhihu.com/p/358605587
pip安装源配置,👉https://www.cnblogs.com/zhangmingyan/articles/11985481.html