【技巧】利用ffmpeg/Streamlink+Artplayer做拉流中转

  1. 1. 搭建环境
  2. 2. 正式搭建
    1. 2.1. 安装 Nginx 环境
    2. 2.2. 安装 ffmpeg
    3. 2.3. 配置 Nginx
      1. 2.3.1. 使用 nginxconfig.io 生成配置
      2. 2.3.2. 开始加入 nginx-rtmp 相关参数:
    4. 2.4. 搭建dplayer播放器
      1. 2.4.1. 去除网页请求的.html后缀
    5. 2.5. 使用OBS等软件开启直播
    6. 2.6. 使用ffmpeg拉流转推
    7. 2.7. 使用Streamlink拉流转推
      1. 2.7.1. 安装Streamlink 与 Screen
      2. 2.7.2. 转推流媒体(以YouTube直播为例)
    8. 2.8. 转推YouTube 非公开(Unlisted)直播流【淦】
      1. 2.8.1. 安装Screen
      2. 2.8.2. 下载并部署yt-dlp
      3. 2.8.3. 利用Screen开启后台运行
      4. 2.8.4. 转推YouTube非公开直播
    9. 2.9. 战渣浪
  3. 3. 鸣谢
    1. 3.1. 参考链接

搭建环境


本文使用 Ubuntu 22.04 进行搭建
本文取消了宝塔面板作为 nginx 控制面板,使用完全命令行方式配置【2023/10/22更新】

正式搭建


安装 Nginx 环境

  • 添加Ondřej Surý 的 PPA源(Ubuntu):

    1
    add-apt-repository ppa:ondrej/nginx-mainline -y
  • 安装 Nginx:

    1
    apt update -y && apt install nginx-extras -y
  • 确认 Nginx 版本和安装位置:

    1
    2
    nginx -V
    whereis nginx
  • 安装 nginx-rtmp-module:

    1
    apt install libnginx-mod-rtmp libnginx-mod-http-lua -y
  • 创建网站目录:

    1
    mkdir -p /var/www/your.site/hls

安装 ffmpeg

1
apt-get -y install ffmpeg  

配置 Nginx

使用 nginxconfig.io 生成配置

  1. 打开 Nginxconfig.io ,使用以下配置:

  1. 接下来根据网站中 使用配置 部分的说明进行配置。需要注意:

    在我的服务器这边测试 certbot 始终无法获取证书,经查可能是网站暂时无法访问导致,因此使用 standalone 模式进行申请。申请前需要暂时停止 Nginx 服务,申请成功后再打开。

    1
    2
    3
    sudo systemctl stop nginx
    certbot certonly --standalone -d 你的网站 --email 你的邮箱 -w /var/www/_letsencrypt -n --agree-tos --force-renewal
    sudo systemctl start nginx

开始加入 nginx-rtmp 相关参数:

  1. 打开 /etc/nginx/nginx.conf,在 http 字段前添加如下内容(请记得删除 #与后面的内容):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
rtmp  {  
server {
listen 1935; ##这是RTMP协议默认端口
chunk_size 4096; ##数据分块大小
application live { ##名为live的项目,可随意改变,但需要和网站配置中相同
live on; ##这是个直播项目
hls on; ##开启HLS录制
wait_key on; ##让视频流从一个关键帧开始
hls_path /var/www/your.site/hls; ##HLS录制文件保存的目录,修改'/var/www/your.site/hls'为你网站的目录
hls_fragment 5s; ##HLS生成的每个ts文件的时长
hls_playlist_length 30s; ##每个ts文件的保留时间
hls_continuous on; ##让HLS标号从上一个结束的位置开始
hls_cleanup on; ##自动清理过时的ts文件
hls_nested on; ##为每一个HLS推流项目建立一个新的子目录
}
}
}

并按ctrl+s保存,之后输入 sudo nginx -t && sudo systemctl reload nginx 保存配置

  1. 修改网站配置
  • 打开 /etc/nginx/sites-enabled/your.site.conf ,并在开头的 server 字段加入以下内容,示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
root /var/www/live/;

# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

# security
include nginxconfig.io/security.conf;

# logging
access_log /var/log/nginx/access.log combined buffer=512k flush=1m;
error_log /var/log/nginx/error.log warn;

# additional config
include nginxconfig.io/general.conf;

# 需要加入本字段
location /stream {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /var/www/live/hls;
add_header Cache-Control no-cache;
}
# 加入字段到此结束,其余配置不要修改!!!
}

# subdomains redirect
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name *.example.com;

# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
return 301 https://example.com$request_uri;
}

# HTTP redirect
server {
listen 80;
listen [::]:80;
server_name .example.com;
include nginxconfig.io/letsencrypt.conf;

location / {
if (!-e $request_filename){
rewrite ^(.*)$ /$1.html last;
break;
}
return 301 https://example.com$request_uri;
}
}

配置好之后,输入 sudo nginx -t && sudo systemctl reload nginx 应用配置,如果看到 xxxx successful 则表示配置正常且已开始使用。

搭建dplayer播放器

/var/www/your.site (与HLS文件夹同目录)下创建一个html文件,并修改为以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE HTML>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LIVE</title>
<link rel="icon" type="image/x-icon" href="https://gcore.jsdelivr.net/gh/imbalaomao/picx-images-hosting@master/image.4akbdjz0ewy0.png">
<script src="https://gcore.jsdelivr.net/npm/hls.js/dist/hls.min.js"></script>
<script src="https://gcore.jsdelivr.net/npm/artplayer/dist/artplayer.js"></script>
<style>
.artplayer-app {
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>
</head>
<body>
<div class="artplayer-app"></div>
<script>
var art = new Artplayer({
container: '.artplayer-app',
url: '/hls/test/index.m3u8',
volume: 0.5,
autoplay: true,
autoSize: true,
fullscreen: true,
fullscreenWeb: true,
isLive: true,
customType: {
m3u8: function playM3u8(video, url, art) {
if (Hls.isSupported()) {
if (art.hls) art.hls.destroy();
const hls = new Hls();
hls.loadSource(url);
hls.attachMedia(video);
art.hls = hls;
art.on('destroy', () => hls.destroy());
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = url;
} else {
art.notice.show = 'Unsupported playback format: m3u8';
}
}
},
});
</script>
</body>

去除网页请求的.html后缀

/etc/nginx/nginxconfig.io/general.conf 中加入如下重写字段:

1
2
3
4
5
6
7
location ^~ / {  
if (!-e $request_filename){
rewrite ^(.*)$ /$1.html last;
break;
}
try_files $uri $uri/ =404;
}

保存后输入 sudo nginx -t && sudo systemctl reload nginx 应用配置即可

使用OBS等软件开启直播

image
设置如下:

  • 服务器:rtmp://你的服务器地址:1935/live/
  • 串流密钥:随意设置,但应与HTML代码中的推流码一致

使用ffmpeg拉流转推

大致命令如下:

1
ffmpeg -i 拉流地址 -c:v copy -c:a aac -b:a 192k -strict -2 -f flv rtmp://127.0.0.1:1935/live/推流码  

如果需要后台运行

1
nohup ffmpeg -i 拉流地址 -c:v copy -c:a aac -b:a 192k -strict -2 -f flv rtmp://127.0.0.1:1935/live/推流码 &  

使用Streamlink拉流转推

1
2
apt-get install python3-pip screen  
pip3 install streamlink

转推流媒体(以YouTube直播为例)

1
2
3
echo "Please input the youtube url:"  
read URL
streamlink $URL best -O | ffmpeg -re -i pipe:0 -c copy -bsf:a aac_adtstoasc -f flv rtmp://localhost:1935/live/youtube

转推YouTube 非公开(Unlisted)直播流【淦】

这个玩意真的折腾死我了,公开直播的转推似乎真的非常简单,而Unlisted直播由于受到保护,Streamlink无法转推,因此进行了一波取巧操作。

这种转推的前提是你要知道直播流的地址,如https://youtu.be/abcdefg

安装Screen

1
apt -y install screen  

我对于后台运行只会screen……我菜鸡我……

下载并部署yt-dlp

1
wget -O /usr/local/bin/yt-dlp https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp  

利用Screen开启后台运行

1
screen -S youtube  

转推YouTube非公开直播

为了这个东西折腾死我了……

1
2
3
4
clear  
echo "Please input the YouTube url:"
read URL
ffmpeg -re -i $(yt-dlp -f best -g $URL) -c copy -bsf:a aac_adtstoasc -f flv -buffer_size 256M rtmp://localhost/live/youtube

这里是利用 yt-dlp 将YouTube直播链接解析为m3u8链接并传递给ffmpeg读取,且buffer_size设置较小似乎会报错(我也不知道为什么,反正调大就对了)。

战渣浪

  • 微博直播后台开播

  • 使用以下代码转推流媒体

    1
    2
    3
    4
    5
    6
    #!/bin/bash
    clear
    read -p "Enter the original file address: " URL
    echo ""
    read -p "Enter Weibo stream link: " LINK
    streamlink $URL best -O | ffmpeg -re -i pipe:0 -c copy -f flv $LINK
  • 使用以下代码在网页中调用微博直播流

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    <!DOCTYPE HTML>
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LIVE</title>
    <link rel="icon" type="image/x-icon" href="https://gcore.jsdelivr.net/gh/imbalaomao/picx-images-hosting@master/image.4akbdjz0ewy0.png">
    <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/hls.js/1.1.5/hls.min.js"></script>
    <script src="https://gcore.jsdelivr.net/npm/artplayer/dist/artplayer.js"></script>
    <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/flv.js/1.6.2/flv.min.js"></script>
    <style>
    .artplayer-app {
    margin: auto;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    }
    </style>
    </head>
    <body>
    <div class="artplayer-app"></div>
    <script>
    function playFlv(video, url, art) {
    if (flvjs.isSupported()) {
    if (art.flv) art.flv.destroy();
    const flv = flvjs.createPlayer({ type: 'flv', url });
    flv.attachMediaElement(video);
    flv.load();
    art.flv = flv;
    art.on('destroy', () => flv.destroy());
    } else {
    art.notice.show = 'Unsupported playback format: flv';
    }
    }

    var art = new Artplayer({
    container: '.artplayer-app',
    url: '微博直播地址',
    type: 'flv',
    isLive: true,
    autoplay: true,
    volume: 0.5,
    poster: 'https://gcore.jsdelivr.net/gh/imbalaomao/picx-images-hosting@master/13人.6627l1ukmpg0.webp',
    customType: {
    flv: playFlv,
    },
    });

    art.on('ready', () => {
    console.info(art.flv);
    });
    </script>
    </body>

鸣谢

感谢 yt-dlp、Streamlink、ffmpeg作者,没有他们就没有此篇教程。

参考链接