当前位置: 欣欣网 > 码农

流媒体HLS传输协议的直播加密播放解决方案

2024-03-10码农

HLS

概述

HTTP Live Streaming(缩写是HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。是苹果公司QuickTime X和iPhone软件系统的一部分。它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的extended M3U (m3u8)playlist文件,用于寻找可用的媒体流。

HLS采用HTTP协议传输音视频数据,HLS通过将音视频流切割成一个个小的TS切片及生成m3u8的播放列表文件,播放客户端通过HTTP协议下载播放列表文件,按照播放列表文件制定的顺序下载切片文件并播放,从而实现便下载边播放,类似于实时在线播放的效果。由于传输层只采用HTTP协议,因此其具备HTTP的网传优势,比如可以方便的透过防火墙或者代理服务器,可简单的实现媒体流的负载均衡,可以方便的结合CDN进行媒体分发等,另外HLS协议本身可实现码率自适应,通过视频转码,切片成不同码率的TS文件,从而实现播放客户端根据网络带宽情况,自由的选择码流进行播放,但是HLS在直播时延时较大。

优劣势

  • 优势 :客户端支持简单,H5 video即可直接播放;网络兼容性好,可很方便的通过防火墙或代理服务器,可很简单的实现媒体流的负载均衡,CDN支持良好;自带多码率自适应机制,实现播放码率自由选择

  • 劣势 :延时较高,不能用于对延时较为苛刻的场景,如互动直播领域;TS切片较多,特别是实时视频流,需要动态的生成和删除TS切片文件,为了实现高性能、低碎片化,对于文件存储的逻辑需要更加复杂的设计

  • 直播加密实现

    HSL 可播放地址

  • https://hls-auth.tinywan.com/hls/202403101/index.m3u8

  • https://hls-auth.tinywan.com/hls/202403102/index.m3u8

  • HTTPS密钥满足条件

  • 您需要在HTTPS服务器上安装受信任机构签署的SSL证书。

  • 密钥文件的验证域必须与第一个播放列表文件的验证域相同。最简单的方法是从HTTPS服务器提供变体播放列表文件 - 变体播放列表文件只下载一次,所以这不会造成太大的负担。其他播放列表文件可以使用HTTP提供。

  • 您必须启动自己的对话框以供用户进行身份验证,或者必须将凭据存储在客户端设备上--HTTP Live Streaming不提供用于身份验证的用户对话框。如果您正在编写自己的客户端应用程序,则可以存储凭据,无论是基于Cookie还是基于HTTP摘要,并在didReceiveAuthenticationChallenge回调中提供凭据(请参阅使用NSURLConnection和身份验证挑战和TLS链验证以了解详细信息)。您提供的凭据将被缓存并由媒体播放器重新使用。

  • 注意:您必须获得受信任的权威机构签署的SSL证书才能使用具有HTTP Live Streaming的HTTPS服务器

    RTMP 直播配置

     rtmp {
    notify_method get;
    server {
    listen 1935;
    chunk_size 4000;
    application live {
    live on;
    hls on;
    hls_path /tmp/hls;
    hls_fragment 6;
    hls_keys on;
    hls_key_path /tmp/keys;
    hls_key_url https://hls-auth.tinywan.com/keys/;
    hls_fragments_per_key 10;
    hls_playlist_length 36s;
    hls_sync 100ms;
    hls_fragment_naming system;
    hls_fragment_slicing aligned;
    }
    }
     }

    推流地址: rtmp://live.tinywan.com/live_auth/123

    HLS 虚拟主机配置

    server {
    listen 443 ssl http2;
    server_name live.tinywan.com;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/www.tinywan.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com/privkey.pem;
    server_tokens off;
    location /live {
    add_header Cache-Control no-cache;
    add_header 'Access-Control-Allow-Origin''*' always;
    add_header 'Access-Control-Expose-Headers''Content-Length,Content-Range';
    add_header 'Access-Control-Allow-Headers''Range';
    types {
    application/vnd.apple.mpegurl m3u8;
    video/mp2t ts;
    }
    root /tmp;
    }
    }

    配置说明:

    1. 播放流地址: https://live.tinywan.com/live_auth/12345.m3u8

    2. m3u8 文件目录位置: /tmp/live_auth

    3. 匹配原则:location 用于匹配 url 是模糊匹配

  • 没有 / 时, location /abc/def 可以匹配 /abc/defghi 请求,也可以匹配 /abc/def/ghi

  • 而有 / 时, location /abc/def/ 不能匹配 /abc/defghi 请求,只能匹配 /abc/def/anything 这样的请求

  • 所以: location /live 可以匹配地址 /live_auth/12345.m3u8

  • 最终匹配的目录: /tmp/live_auth/12345.m3u8

  • HLS-KEY虚拟主机配置

    server {
    listen 443 ssl http2;
    server_name hls-auth.tinywan.com;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/www.tinywan.com-0002/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.tinywan.com-0002/privkey.pem;
    server_tokens off;
    # hls keys
    location /keys {
    add_header Cache-Control no-cache;
    add_header 'Access-Control-Allow-Origin''*' always;
    add_header 'Access-Control-Expose-Headers''Content-Length,Content-Range';
    add_header 'Access-Control-Allow-Headers''Range';
    access_by_lua_file /usr/local/openresty/nginx/conf/lua/filter_domain_ip_limit.lua;
    root /tmp;
    }
    }

    Lua 脚本 filter_domain_ip_limit.lua

    local redis = require("resty.redis")
    local var=ngx.var
    locallog = ngx.log
    local ERR = ngx.ERR
    local EXIT = ngx.exit
    -- redis config
    local redis_host = "127.0.0.1"
    local redis_port = 6379
    local redis_auth = "tinywanredisamaistream"
    local redis_timeout = 1000
    local red = redis:new()
    red:set_timeout(redis_timeout)
    local ok, err = red:connect(redis_host, redis_port)
    ifnot ok then
    log(ERR, "connect to redis error : ", err)
    end
    -- client info
    local client_ip = ngx.req.get_headers()['X-Real-IP']
    if client_ip == nilthen
    client_ip = ngx.req.get_headers()['X-Forwarded-For']
    end
    if client_ip == nilthen
    client_ip = ngx.var.remote_addr
    end
    local req_origin = ngx.req.get_headers()['origin']
    -- local h = ngx.req.get_headers()
    -- for k, v in pairs(h) do
    -- log(ERR,k.." k-----------v: "..v)
    -- end
    if req_origin == nilthen
    red:zadd('HTTP_REQUEST_UNAUTHORIZED',ngx.time(),client_ip)
    log(ERR, 'not http request origin is nil IP::'..client_ip)
    EXIT(ngx.HTTP_UNAUTHORIZED)
    end
    -- redis action
    iftostring(req_origin) ~= "https://www.tinywan.com"then
    red:zadd('HTTP_REQUEST_FORBIDDEN',ngx.time(),req_origin)
    log(ERR, "error : request origin is error req_origin = "..req_origin)
    EXIT(ngx.HTTP_FORBIDDEN)
    end




    注意:通过以上加密授权验证,只能在 tinywan.com 域名下进行播放,其他地方将无法播放(包括VLC也是无法播放的)