在數位內容消費快速演變的今日,串流媒體已從一種新興技術發展成為主流的內容傳遞方式。這種趨勢不僅改變了消費者行為,也促使內容創作者和傳統媒體公司重新思考他們的商業模式。在本文中,我們將探討串流技術的推流機制,並親自操作設置伺服器,藉此加深我們對這項技術的理解。
素材取用
影片:雲端下載 <影片來源 – Bad Apple by あにら | ニコニコ >
事前準備
本篇實作之過程採用 Red5 Open Source 之容器架設,而擁有較高彈性設定網址指標。請參考此篇文章進行 Docker 安裝。
概念釐清
什麼是串流?
或許各位在日常生活中時常會觀看串流影片或聆聽串流音樂,但你是否曾經思考過,除了「需要網路連線」這個基本需求之外,串流技術背後還隱藏著什麼奧秘呢?其技術核心概念其實相當精妙,它會將多媒體內容依照固定的時間長度切分成許多碎片,系統會在播放間持續不斷地下載後續的片段,並無縫地將它們串接起來進行播放,因此也不用等待完整的檔案下載完畢。
這種串流方式讓用戶不必購買或下載龐大的實體檔案存在設備,在處理 Hi-Res 音樂專輯或高畫質電影時特別明顯,因為這類檔案動輒就是 GB 起跳的容量,而且多數用戶可能只會偶爾觀看或收聽。但這種服務也存在一些明顯的限制,尤其觀看品質依賴於提供商的服務品質以及使用者的網路連線狀況。另外由於持續下載片段消耗大量網路流量,因此沒有網路吃到飽方案的用戶通常也會盡可能地避開串流服務。
同樣的機制也能解釋了為什麼在目前實際使用串流服務時,往往很難獲得與本地播放相同等級的高品質影音體驗。回想關於 Bit-Rate 的定義,此時則會變成每秒在網路間所需的傳輸量。如果拿筆者在 MORA 上購買的 <VIOLET EVERGARDEN: Automemories> 這張專輯來說,每首音樂都需要每秒約略 4Mb 的傳輸速度。對於許多的用戶來說,就已經是一個難關,而如 YouTube Music 或 Spotify 則也需要更大的基礎建設,因此現在都仍維持提供基本的 360 kbps。
至於 Spotify HiFi 的推出時程,從 2021 年初次公布這項計畫以來,已經過了相當長的一段時間。而這項備受期待的功能最終會以什麼樣的形式呈現,以及何時能真正讓用戶體驗到,目前依然是一個懸而未決的問題。
這邊筆者相信,各位能最直觀感受到的肯定是在觀看 YouTube 影片時,播放進度列上方的白色條狀區域,它實際上代表了已經成功下載並緩存到你設備上的影片片段。而這個時候我們可以將直播再分為兩類:直播串流與隨選視訊。直播 (Live) 的概念就是伺服器頭也不回地狂衝猛衝,現在播到哪,訪客就看到哪。而隨選 (Video on Demand, VoD) 則是訪客可以自由選擇要看什麼,並且可以從頭到尾自己控制,而不是伺服器統一撥放。
這個區塊主要面向技術人員。由於影片在撥放時,畫面變化快速其實人眼不太會注意到過多細節,因此通常使用 UDP 協議來加速傳輸,反正掉包也不太影響大局。然後針對這些跨國網路傳輸,一般都會擁有 CDN 網路,透過在網路的多個節點保存備份,減少網路間的距離。
實作過程
即時串流
預錄撥放
不知各位有沒有看過如木棉花推出的動漫馬拉松直播活動,這種長時間的節目安排難道真的是員工坐在那裡很開心的邊看邊直播嗎?實際上,這類直播串流通常採用的是預先處理好的影片內容,只需要依照排程將它們掛載到專門的串流伺服器上,系統便能自動按照設定的時間表進行播放,無需人工實時操作。
這種自動化的串流方式不僅大幅減輕了技術人員的工作負擔,也能確保觀眾獲得穩定且高品質的觀看體驗。而透過下方的指令,我們可以在不做任何調整的情況,輕鬆地將影片掛載到伺服器上。
ffmpeg -re -i ./test.mp4 -f flv rtmp://localhost/live/livesteam0
然而這樣的方式沒法辦到洗腦直播,除非我們預先將影片不斷剪貼好幾次,但終究會有結束的時間,而且還會徒增檔案大小。這個時候就能依靠 -stream_loop 這個參數,這邊數字多少代表重複撥放幾次,而 -1 則代表無限循環直到關閉。
ffmpeg -re -stream_loop -1 -i ./test.mp4 -f flv rtmp://localhost/live/livesteam0
可是動漫馬拉松肯定是每集撥放,這樣的重複沒有作用阿?這個時候我們只需要讓腳本在資料夾內執行迴圈,或者手動新增一行指令將每集撥放,就可以完美達成。各位可以嘗試複製第一行的指令,貼到腳本第二行後執行看看。就是如此簡單便可達成無縫接軌的直播流程。
互動鏡頭
假設我們今天要架設私人之間的視訊會議,則勢必需要動用到攝像頭與音訊的抓取,而這個時候我們需要先找到我們有那些設備。
ffmpeg -list_devices true -f dshow -i dummy

接者就需要透過 dshow 來呼叫我們的設備,而這邊我們可以直接從 Command Prompt 上複製文字之後,貼上到程式碼的指定位置。為了優化串流品質並盡可能減少視訊傳輸過程中的延遲問題,這邊建議在設定中加入幾項額外的參數。
:: 使用 UTF-8 編碼
chcp 65001 > nul
ffmpeg -f dshow -i video="(CAM)":audio="(MIC)" -preset ultrafast -vcodec libx264 -tune zerolatency -b 2500k -f flv rtmp://localhost/live/livestream0
然而,RTMP 的速度仍遠不及 WebRTC 協議的即時性,實際上兩者有著約 5 秒 與 5 毫秒 的巨大差距。此外,WebRTC 採用的也是 HTTP 協議,相較而言更為普及,但 Red5 的開源版本中並未包含這項協議。這邊額外附上整天在掙扎安裝與研究串流伺服器而已經笑不出來的某人。

隨選影片
即時直播是個相對簡單的概念,主打主伺服器播放到哪,入場觀眾就從哪收看。這種機制非常類似於電視節目,觀眾只能從當前放映的劇情開始觀看,錯過的內容就無法回溯。如果使用機上盒錄影,又會占用儲存空間,無法保存所有喜歡的影片。
正是因為這種限制,VoD 逐漸發展成為一種更加靈活的主流觀影方式。這種服務模式徹底改變了人們的觀影習慣,使觀眾能夠完全按照自己的時間安排來享受視聽內容。無論何時何地,只要有網路連接,用戶就能開啟如 Netflix、Disney+ 這些串流平台開始收看自己喜愛的影片,不必受限於檔案大小與固定的播放時間表。
轉檔過程
而關於 VoD 之設定,我們則需要仰賴於使用 HTTP 的 HLS 協議,透過 m3u8 作為索引清單,將切塊後的 ts 區塊加載,確保用戶就算跳動時間軸也只需下載播放位置後方的小量內容。
並非所有的工具都允許 RTMP 轉 HLS,而且這個步驟也難免有些的問題存在。所以我們之前在建立 Red5 容器的時候,才會特別同步本機與容器的目錄,要將處理好的影片直接擺上伺服器。但不用擔心,關於這個部分我幫各位整理成下方稍微繁瑣的腳本。
@echo off
setlocal enabledelayedexpansion
:: 媒體儲存位置
if not exist "C:\Red5\media\uncategory" mkdir "C:\Red5\media\uncategory"
:: Check if input file was provided
if "%~1"=="" (
echo Please provide an input video file.
goto :eof
)
:: Generate a random UUID for the video
set "uuid="
for /f "delims=" %%i in ('powershell -command "[guid]::NewGuid().ToString()"') do set uuid=%%i
:: Extract filename without extension
set "filename=%~n1"
:: Create category directory if specified, otherwise use uncategory
set "category=uncategory"
if not "%~2"=="" set "category=%~2"
if not exist "C:\Red5\media\%category%\%uuid%" mkdir "C:\Red5\media\%category%\%uuid%"
:: Convert video to HLS format
ffmpeg -i "%~1" -c:v libx264 -preset veryfast -b:v 2500k -c:a aac -b:a 128k -f hls ^
-hls_flags split_by_time -hls_time 3 -hls_list_size 0 ^
-hls_segment_filename "C:\Red5\media\%category%\%uuid%\%filename%_%%03d.ts" ^
"C:\Red5\media\%category%\%uuid%\%filename%.m3u8"
echo Video converted and saved to: C:\Red5\media\%category%\%uuid%\%filename%.m3u8
使用方式如下,在範例中我們將 ./test.mp4 這個影片檔案轉換輸出為 m3u8 格式,並存放在 test 分類資料夾之中,而轉換完成後,系統會自動為這個影片指派 UUID。首先,這樣可以避免大量 ts 檔案全部混雜在同一個目錄中造成數量龐雜;其次,每個影片都有一個獨特的識別碼,可以讓後端系統中索引和管理這些媒體資源變得更加方便和有條理。
./vod.bat |待轉檔的影片| |分類|
./vod.bat ./test.mp4 test
影片路徑
執行完成之後會輸出一個路徑,我們將 \media\ 之後的片段複製下來,然後把 \ 改成 /。
test/3b64b3ed-dde3-4f48-af60-bdf4863b8dc9/test.m3u8
將其接到這個網址的後方,這是 Red5 預設執行 VoD 的功能主頁。
http://localhost:5080/vod/streams/
但是在 PotPlayer 跟 VLC 都顯示 03:39 的時間長度,而且撥放起來很正常,整體體驗與直接播放本地檔案幾乎無異。所以筆者,確定這個設置實現媒體串流功能,而不只是普通的檔案存取嗎?
我自己也很疑惑,所以特別寫了一個網頁擺設撥放器 (這個測試需要開通 CORS 功能),並透過 Chrome DevTools 確認。此時可以看到持續的有 .ts 檔案被讀取,而當筆者跳動時間軸,則從 15 直接跳到 41 (02:03) 並在短時間內連續到 52,之後再度慢速下載接續的部分。

後話
隨著網路基礎設施的持續優化和新技術的不斷涌現,串流媒體服務將繼續發展並提升用戶體驗。低延遲串流技術使得即時互動成為可能,而更智能的自適應串流算法則能夠根據網路狀況即時調整影片品質,同時確保觀看體驗的連續性。這些技術突破將為串流媒體的未來奠定堅實基礎,同時也為內容創作者和平台提供更多可能性。
而我們先前探討 FFmpeg 的推流方式,以及後續針對 HLS 協議的轉檔方式,並實際嘗試 Live 與 VoD 兩種形式。通過這些實作,我們不僅觸碰串流媒體背後的技術原理,還掌握了如何搭建和配置自己的串流伺服器。希望本文的實作內容能為讀者提供實用的參考,並激發更多關於串流媒體技術應用的創新想法。
*筆者花費整整 3 天研究關於串流的東西,還望各位多多支持 QAQ
參考
[1] Streaming — FFmpeg Bug Tracker and Wiki
https://trac.ffmpeg.org/wiki/StreamingGuide
[2] FFmpeg – the swiss army knife of Internet Streaming – Part IV
https://sonnati.wordpress.com/2011/08/30/ffmpeg-%e2%80%93-the-swiss-army-knife-of-internet-streaming-%e2%80%93-part-iv/
[3] HLS Packaging using FFmpeg
https://ottverse.com/hls-packaging-using-ffmpeg-live-vod/
[4] flv — FFmpeg
https://ffmpeg.org/ffmpeg-formats.html#flv_002c-live_005fflv_002c-kux
[5] hls — FFmpeg
https://ffmpeg.org/ffmpeg-formats.html#hls-1
額外讀物
[1] What is HLS — Cloudflare
https://www.cloudflare.com/zh-tw/learning/video/what-is-http-live-streaming/
[2] Spotify HiFi — Spotify Newsroom
https://newsroom.spotify.com/2021-02-22/five-things-to-know-about-spotify-hifi/