Linux下使用FFmpeg将RTMP流转换为HLS

Posted 你知道989

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux下使用FFmpeg将RTMP流转换为HLS相关的知识,希望对你有一定的参考价值。

Linux下使用FFmpeg将RTMP流转换为HLS

所需资料

安装FFmpeg

由于CentOS没有官方FFmpeg rpm软件包。但是,我们可以使用第三方YUM源(Nux Dextop)完成此工作。

sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro

sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm

安装FFmpeg 和 FFmpeg开发包

sudo yum install ffmpeg ffmpeg-devel -y

测试FFmpeg

ffmpeg -h

配置安装nginx并添加nginx-http-flv-module到nginx中

依次安装系统相关依赖项

yum -y install unzip
yum -y install gcc-c++ 
yum -y install pcre pcre-devel  
yum -y install zlib zlib-devel 
yum -y install openssl openssl-devel

将nginx-http-flv-module和nginx上传并解压到/usr/local/nginx中

cd /usr/local/nginx
tar -zxvf nginx-1.8.1.tar.gz
unzip nginx-http-flv-module-1.2.6.zip

进入nginx目录下编译安装nginx

cd nginx-1.8.1
./configure --prefix=/usr/local/nginx  --add-module=/usr/local/nginx/nginx-http-flv-module
make && make install

prefix为nginx的安装的目录
add-moudle为nginx-http-flv-module的目录

配置Nginx 以实现流转换

配置RTMP

rtmp 
    server 
       listen 1935;
​
       application myapp 
           live on;
       
       application live 
             live on;   #开启实时
             hls on;    #开启hls
             hls_path /usr/local/etc/nginx/html/multimedia/hls;  #hls的ts切片存放路径
             hls_fragment 2s;         #本地切片长度
             hls_playlist_length 6s;  #HLS播放列表长度
       
    

配置HLS拉流

location /live 
    types 
        application/vnd.apple.mpegurl m3u8;
        video/mp2t ts;
    
    alias /usr/local/etc/nginx/html/multimedia/hls/;
    add_header Cache-Control no-cache;

完整nginx配置

user  nginx;

# 自动分配工作进程数
worker_processes  auto;

# 绑定cpu
worker_cpu_affinity auto;

# 指明worker进程的ince值
worker_priority -15;

# 错误日志存放位置
error_log  /var/log/nginx/error.log warn;
# pid文件存放位置
pid        /var/run/nginx.pid;

events 
    worker_connections  1024;
    accept_mutex on;         # 设置单个请求只唤醒一个进程
    multi_accept on;         # 设置一个工作进程可接收多个新网络连接


rtmp 
    server 
        listen 1985;

        application myapp 
            live on;
        

       application live 
             live on;   #开启实时
             hls on;    #开启hls
             hls_path /home/server/hls;  #hls的ts切片存放路径
             hls_fragment 2s;        
             hls_playlist_length 6s;
        
       

http 
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    server_tokens off;      #隐藏版本号
    client_max_body_size 50m;   #调整nginx上传文件限制
    keepalive_timeout  65;

    #gzip  on;  开启压缩
    gzip on;
    gzip_vary on;
    gzip_buffers 16 8k;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/jpeg image/gif image/png application/x-protobuf;

    server 
        listen       1997;
        server_name  localhost;

        location / 
            root   html;
            index  index.html index.htm;
        

        error_page   500 502 503 504  /50x.html;
        location = /50x.html 
            root   html;
        

        location /live/ 
            types 
        	    application/vnd.apple.mpegurl m3u8;
       		    video/mp2t ts;
            
            alias /home/server/hls/;
            add_header Cache-Control no-cache;
        

    



添加nginx软连接

ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx

启动nginx

nginx

使用FFmpeg进行转流

测试流地址:
rtmp://media3.scctv.net/live/scctv_800

使用ffmpeg进行转换

ffmpeg -re -i rtmp://media3.scctv.net/live/scctv_800 -c copy -f flv rtmp://127.0.0.1:1997/live/test

第一行的地址为测试地址
第二个地址为nginx中配置的rtmp中的live
第二个地址的IP需更改为nginx的服务器IP , 端口为rtmp中配置的端口
test部分为自定义 , 是hls文件夹下的.m3u8和切片的名称

测试拉流

使用vlc在windows中测试
拉流地址为 :

http://127.0.0.1:1997/live/test.m3u8

此处的test和ffmpeg转换的第二个地址末尾的test相对应

FFmpeg命令读取RTMP流如何设置超时时间

子标题:FFmpeg命令录制RTMP流为FLV文件时如何设置超时时间 | FFmpeg命令如何解决录制产生阻塞的问题  
0x001: 前言


今天在测试程序时遇到两个问题。
Q1:ffmpeg录制RTMP流并保存为FLV文件时,推RTMP流的线程已经结束断掉了,而录制的线程却还一直在录。
Q2:ffmpeg录制RTMP流并保存为FLV文件时,被录制的RTMP流并未推流或并无此房间频道,而录制的线程却还一直在录。

观察日志文件发现录制程序一直阻塞在某个时间点上,经查验这是因为ffmpeg在拉取RTMP流时只要流媒体服务器能正常访问,不管当前拉取的流是否能正常访问都不会退出。
举个例子:rtmp://192.168.1.100:1935/live/changfang,只要192.168.1.100:1935这个服务器地址是能正常请求通的,不管当前changfang频道有没有在推流,ffmpeg都会阻塞至此。当你把整个服务器down掉,你会发现ffmpeg录制的程序会立马退出不再阻塞。此时第一个想法就是寻找设置超时的命令参数。

0x002: 解决方案


遇到问题就找找有没有前人也遇到类似情况,找了一遍基本是C++代码如何解决的问题,没有ffmpeg命令相关的结果。于是查看命令帮助,寻找timeout字眼,找了很多参数,经多次尝试发现有个 -rw_timeout

这是官方描述:
-rw_timeout        <int64>      ED....... Timeout for IO operations (in microseconds) (from 0 to I64_MAX) (default 0)

技术图片


读取流也属于IO操作,但此处要注意两点:1.参数单位是微秒,而不是秒。1秒(s)=1000000微秒(μs)   2.参数要放在开流前,否则不会生效

更改前的命令(为了便于分析观看,只留最基础的命令):

ffmpeg -i rtmp://192.168.1.100:1935/live/changfang -c copy -f flv /opt/video/123.flv

更改后的命令:

ffmpeg -rw_timeout 5000000 -i rtmp://192.168.1.100:1935/live/changfang -c copy -f flv /opt/video/123.flv


这样,不管是推流结束还是从未推过流,只要ffmpeg在开流时,IO操作超过设置的秒数,就会自动退出。(如果你读取的流是外网流或内网流不太通畅的情况下,不建议你把此时间设置过短,因为ffmpeg在录制时从开流到产生FLV录制文件也需要时间)

 

0x003: 完结


如果你正好遇到此问题,希望能帮到你!


以上是关于Linux下使用FFmpeg将RTMP流转换为HLS的主要内容,如果未能解决你的问题,请参考以下文章

Linux下librtmp使用及编程实战

如何将实时 RTMP 视频转换为实时 mp3 Icecast 流

使用FFMPEG在windows平台下推rtmp流

FFmpeg常用推流命令

搭建HLS推流环境

使用 FFmpeg 通过 RTMP 发送 H.264 编码流