基于OSS構(gòu)建HLS流
OSS支持以RTMP協(xié)議推流音視頻至存儲空間(Bucket),并轉(zhuǎn)儲為HLS協(xié)議格式,同時提供了豐富的鑒權(quán)、授權(quán)機制實現(xiàn)更細顆粒度的音視頻數(shù)據(jù)訪問控制。
前提條件
已創(chuàng)建了存儲空間。具體操作,請參見控制臺創(chuàng)建存儲空間。
基礎(chǔ)操作
OSS支持使用RTMP推流協(xié)議上傳H264格式的視頻數(shù)據(jù)和AAC格式的音頻數(shù)據(jù),并通過訪問PlayURL地址的方式獲取音視頻數(shù)據(jù)。
上傳音視頻數(shù)據(jù)
調(diào)用PutLiveChannel接口創(chuàng)建LiveChannel。
調(diào)用該接口會返回RTMP推流地址PublishURL和播放地址PlayURL。您還可以使用SDK的方式創(chuàng)建LiveChannel。更多信息,請參見LiveChannel管理。
通過PublishURL推流音視頻文件。
OSS將上傳的音視頻文件按HLS協(xié)議轉(zhuǎn)儲,即轉(zhuǎn)儲為一個m3u8格式的索引文件和多個ts格式的視頻文件。具體操作,請參見RTMP推流上傳。
獲取音視頻數(shù)據(jù)
您可以通過瀏覽器直接訪問PlayURL地址的方式,即訪問m3u8索引文件的方式來獲取音視頻數(shù)據(jù)。
Android和iOS等移動平臺,以及PC端的少數(shù)瀏覽器例如Microsoft Edge和Safari,支持通過訪問m3u8文件的方式播放視頻。Chrome等瀏覽器需要嵌入Video.js等JavaScript腳本才能正常播放視頻。
您在公共讀寫的Bucket中通過OSS上傳和獲取音視頻,意味著任何人都有權(quán)限讀寫您的音視頻數(shù)據(jù),從而造成不必要的數(shù)據(jù)泄露和流量計費等問題。默認(rèn)情況下,OSS Bucket的訪問權(quán)限為私有,且拒絕任何來源的跨域請求。推薦您根據(jù)自身的使用場景,結(jié)合跨域資源共享CORS、防盜鏈、私有Bucket簽名機制中的一種或多種方式,從而有效保護您的數(shù)據(jù)安全。
跨域資源共享CORS
如果不是通過瀏覽器直接訪問OSS的音視頻,而是先訪問第三方的網(wǎng)頁并在網(wǎng)頁中嵌入了OSS的音視頻,則很有可能遇到跨域問題,導(dǎo)致視頻無法播放。這是因為當(dāng)Web服務(wù)器和OSS不屬于同一個域時,將違反同源策略,瀏覽器默認(rèn)會拒絕該連接。
例如,Web服務(wù)器地址為http://192.168.xx.xx:8080,瀏覽器訪問該地址獲取了網(wǎng)頁,網(wǎng)頁的JavaScript腳本里嵌入了視頻,視頻來源指向OSS Bucket。此時,瀏覽器需要再次向OSS發(fā)送請求,試圖訪問OSS中的視頻數(shù)據(jù)。但是,瀏覽器識別到OSS Bucket的訪問地址與http://192.168.xx.xx:8080的網(wǎng)頁地址不屬于同一個域,則會先向OSS Bucket詢問是否允許跨域請求。OSS Bucket默認(rèn)不開啟CORS配置,因此會拒絕瀏覽器的跨域請求,使得瀏覽器不能正常播放音視頻。如下圖所示:
您可以通過OSS的跨域資源共享,解決因跨域限制導(dǎo)致音視頻無法正常播放的問題。
登錄OSS管理控制臺。
單擊Bucket列表,之后單擊目標(biāo)Bucket名稱。
單擊 。
單擊創(chuàng)建規(guī)則。
在創(chuàng)建跨域規(guī)則頁面配置各項參數(shù)。
結(jié)合本文檔示例場景,請將來源設(shè)置為http://192.168.xx.xx:8080,其他參數(shù)設(shè)置請參見設(shè)置跨域資源共享。
如果來源為具體的域名,請?zhí)顚懲暾挠蛎?span data-tag="option" id="option-3yy-kdt-ni1" class="option">www.example.com,不可省略為example.com。
如果來源為精準(zhǔn)的IP地址,請?zhí)顚懓▍f(xié)議類型和端口號在內(nèi)的完整的IP地址,例如http://xx.xx.xx.xx:80,不可省略為xx.xx.xx.xx。
瀏覽器對跨域配置通常會有數(shù)十秒至幾分鐘的緩存時間。如果希望跨域配置立即生效,建議清空瀏覽器緩存后刷新網(wǎng)頁。
防盜鏈
CORS規(guī)則可以有效阻止其他網(wǎng)站服務(wù)器在網(wǎng)頁中嵌入您的音視頻資源。但如果您通過直接訪問OSS Bucket的方式獲取音視頻,則CORS規(guī)則將失效。在這種情況下,您可以通過OSS防盜鏈對Bucket設(shè)置Referer白名單的機制,避免其他人盜取您的音視頻資源。
默認(rèn)情況下,Bucket允許空Referer,通過本地瀏覽器訪問PlayURL的方式可以直接觀看視頻。為了防止音視頻資源被其他人盜用,您可以將Bucket設(shè)置為不允許空Referer,并將您信任的域名或IP加入Referer白名單。此時,除Referer白名單以外的第三方訪問音視頻資源時均會被拒絕,并返回403 Forbidden錯誤。
登錄OSS管理控制臺。
單擊Bucket列表,之后單擊目標(biāo)Bucket名稱。
在左側(cè)導(dǎo)航欄,選擇數(shù)據(jù)安全>防盜鏈。
在防盜鏈頁面,打開防盜鏈開關(guān)。
在Referer框中,填寫域名或IP地址,例如*.aliyun.com。
您可以結(jié)合實際使用場景設(shè)置不同的Referer字段。Referer配置示例詳情請參見設(shè)置防盜鏈。
在空Referer框中,選擇不允許空Referer。
說明選擇不允許空Referer且設(shè)置了Referer白名單,則只有HTTP或HTTPS header中包含Referer字段的請求才能訪問OSS資源。
選擇不允許空Referer但未設(shè)置Referer白名單,效果等同于允許空Referer,即防盜鏈設(shè)置無效。
單擊保存。
私有Bucket簽名機制
為了保護您的數(shù)據(jù)安全,OSS默認(rèn)Bucket的讀寫權(quán)限為私有。因此當(dāng)您需要向私有Bucket執(zhí)行讀取或?qū)懭氩僮鲿r,需要使用簽名機制向OSS聲明您的操作權(quán)限。
當(dāng)您向私有Bucket推流時,需要對推流地址進行簽名后才能上傳音視頻文件。具體操作,請參見RTMP推流地址及簽名。
使用Python SDK獲取簽名的推流地址示例如下:
示例返回值為字符串形式格式如下:
rtmp://xxx.oss-cn-beijing.aliyuncs.com/live/xxx?playlistName=xxx&OSSAccessKeyId=xxx&Expires=xxx&Signature=xxx
最后Signature的值為簽名,前面的為視頻流的相關(guān)信息。
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 從環(huán)境變量中獲取訪問憑證。運行本代碼示例之前,請確保已設(shè)置環(huán)境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# 填寫B(tài)ucket所在地域?qū)?yīng)的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
# 填寫B(tài)ucket名稱,例如examplebucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
# 創(chuàng)建并配置流頻道。
# 該索引文件包含3個ts文件,每個ts文件的時長為5秒。此示例中的5秒時長為建議值,具體時長取決于關(guān)鍵幀。
channel_name = "your_channel_name"
playlist_name = "your_playlist_name.m3u8"
frag_count_config = 3
frag_duration_config = 5
create_result = bucket.create_live_channel(
channel_name,
oss2.models.LiveChannelInfo(
status = 'enabled',
description = 'your description here',
target = oss2.models.LiveChannelInfoTarget(
playlist_name = playlist_name,
frag_count = frag_count_config,
frag_duration = frag_duration_config)))
# 獲取RTMP推流簽名地址。
# 示例中的expires是一個相對時間,表示從現(xiàn)在開始此次推流過期的秒數(shù)。
# 獲取簽名后的signed_url后即可使用推流工具直接進行推流。一旦連接上OSS,即使超出設(shè)置的expires也不會斷流,OSS僅在每次推流連接時檢查expires是否合法。
signed_rtmp_url = bucket.sign_rtmp_url(channel_name, playlist_name, expires=3600)
print(signed_rtmp_url)
OSS訪問私有Bucket中的文件時,需要在URL中加上簽名。HLS的訪問機制為動態(tài)訪問m3u8索引文件,根據(jù)索引文件的內(nèi)容多次請求下載最新的ts文件,此過程中的每一次請求都需要在URL中加上簽名。
為此,OSS對音視頻數(shù)據(jù)的訪問提供了動態(tài)簽名機制,即只需在首次訪問m3u8文件時在URL中添加x-oss-process=hls/sign
, OSS將對返回的播放列表中的所有ts地址自動按照與m3u8完全相同的方式進行簽名。
使用Python SDK動態(tài)簽名機制訪問音視頻的示例如下:
# 獲取觀流的動態(tài)簽名地址。
your_object_name = "test_rtmp_live/test.m3u8"
style = "hls/sign"
# 生成簽名URL時,OSS默認(rèn)會對Object完整路徑中的正斜線(/)進行轉(zhuǎn)義,從而導(dǎo)致生成的簽名URL無法直接使用。
# 設(shè)置slash_safe為True,OSS不會對Object完整路徑中的正斜線(/)進行轉(zhuǎn)義,此時生成的簽名URL可以直接使用。
signed_download_url = bucket.sign_url('GET', your_object_name, 3600, params={'x-oss-process': style}, slash_safe=True)
print(signed_download_url)