这几天我一直在思考这个问题,但找不到一个“优雅”的解决方案。我想使用 NGINX 服务器作为某些直播频道的流媒体来源,并通过不同的 CDN 进行分发。
乍一看,这个问题很简单,但当涉及到现实生活中的情况时,它就开始变得复杂,我想知道你的看法......
首先,我将多个转码器配置为后端,并且 NGINX 必须能够路由到正确的编码器。为了实现这一点,我使用了类似以下方法:
upstream transcoder_pool_01 {
server 192.168.1.1;
server 192.168.1.2;
}
upstream transcoder_pool_02 {
server 192.168.1.3;
server 192.168.1.4;
}
map $livechannel $backend {
channel1 transcoder_pool_01;
channel2 transcoder_pool_02;
channel3 transcoder_pool_03;
}
到目前为止一切都很好。现在到了困难的部分。
我的转码器/打包器使用以下方案生成流:
主 HLS 清单:http://ip_address/liveapplication/channel_name/master.m3u8
单一 HLS 比特率清单http://ip_address/liveapplication/channel_name/channel_name-RESOLUTION/playlist.m3u8
DASH 清单:http://ip_address/liveapplication/channel_name/manifest.m3u8
片段:(http://ip_address/liveapplication/channel_name/channel_name-RESOLUTION/chunk-xxxxxxx.ts
或 chunk-xxxxxx.mp4,或 chunk-xxxxxx.m4s)
- 请注意,打包程序对于 DASH 和 HLS 共享相同的实时应用程序和段。
现在,由于我无法控制的原因,CDN 需要使用不同的路径处理 DASH 和 HLS。除此之外,同一个 Origin 流在不同的环境和通道块中被重复使用多次。由于这个原因,我的 Origin 从 CDN/Edges 收到如下请求:
http://originserver/live-hls/environment-01/channel-block01/channel-name/master.m3u8
或者
http://originserver/live-dash/environment-01/channel-block02/channel-name/manifest.mpd
或者
http://originserver/live-dash/environment-02/channel-block01/channel-name/channel-name-SD/playlist.m3u8
或者
http://originserver/live-dash/environment-02/channel-block01/channel-name/channel-name-SD/chunk-002314.m4s
等等....
此时,在转发请求之前我需要的是:
- 将“live-dash”或“live-hls”更改为常见的“liveapplication”
- 从 URI 中剥离环境和通道块
- 按原样传递剩余部分,但:3a) 为名为 master.m3u8 和 manifest.mpd 的文件以及所有媒体块设置一个非常长的缓存 3b) 为名为 playlist.m3u8 的文件设置一个非常短的缓存(请注意,这些文件与相关块位于同一子目录中)
我正在考虑临时解决定义类似以下服务器的问题:
server {
listen 80;
server_name originserver;
proxy_redirect off;
proxy_http_version 1.1;
proxy_read_timeout 10s;
proxy_send_timeout 10s;
proxy_connect_timeout 10s;
proxy_ignore_headers Cache-Control;
proxy_ignore_headers Set-Cookie;
proxy_cache liveorigin_cache;
proxy_cache_methods GET HEAD;
proxy_cache_key $uri;
proxy_cache_lock on;
proxy_cache_lock_age 5s;
proxy_cache_lock_timeout 1h;
# cache valid for 5 seconds where not specified differently
proxy_cache_valid 200 302 5s;
proxy_cache_valid 404 1s;
location ~ /(live-hls|live-dash)/([a-z0-9_\.-]+)/([a-z0-9_\.-]+)/([a-z0-9_\.-]+)/(master.m3u8|manifest.mpd) {
proxy_cache_valid 200 400s;
add_header "X-MasterManifest-Tag" "true";
proxy_pass http://$backend/liveapplication/$4/$5;
}
location ~ /(live-hls|live-dash)/([a-z0-9_\.-]+)/([a-z0-9_\.-]+)/([a-z0-9_\.-]+)/(.*)/playlist.m3u8 {
proxy_cache_valid 200 2s;
add_header "X-Playlist-Tag" "true";
proxy_pass http://$backend/liveapplication/$4/$5/playlist.m3u8;
}
location ~ /(live-hls|live-dash)/([a-z0-9_\.-]+)/([a-z0-9_\.-]+)/([a-z0-9_\.-]+)/(.*)/(.*).(ts|mp4|fmp4|m4s) {
proxy_cache_valid 200 2s;
add_header "X-Segments-Tag" "true";
proxy_pass http://$backend/liveapplication/$4/$5/$6/$7;
}
附言:添加的标题是为了让我验证位置是否确实与预期匹配......
但它肯定不起作用。
我暂时“修补”了该问题,将所有位置替换为一个位置,例如:
location ~ /(live-hls|live-dash)/([a-z0-9_\.-]+)/([a-z0-9_\.-]+)/([a-z0-9_\.-]+)/(.*) {
set $livechannel $4;
add_header "X-General-Tag" "true";
proxy_pass http://$backend/live/$4/$5;
}
这是可行的,但当然所有文件都以相同的方式缓存,并且考虑到有无限数量的边与这个原点联系,我确实需要减少转码器的负载。
而且,我也相信有一种方法比我认为的方法更好。
也许可以使用嵌套位置?我真的迷茫了。
谢谢你的帮助。Alex