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