當前位置: 妍妍網 > 碼農

串流媒體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也是無法播放的)