HTTP

M3U8 串流影音 — 概念 與 下載

現今,許多影音媒體網站皆能看到 M3U8 檔案,
以及許多副檔名為 .ts 的分段媒體,
本篇將介紹其基本概念,並說明如何下載成 mp4 檔 😆。
 

 


 

HLS 簡介

Apple Inc. 於 2009 年時提出了 HTTP Live Streaming (HLS),
恰如其名,HLS 是一基於 HTTP(S) 的 串流媒體協議。
[註]:當然,串流傳輸的方式不止這種 (e.g., DASH, RTMP, RTP/RTSP, Range Request)。
 
HLS 的原理是 將媒體分割成多個 副檔名為 .ts 的小檔案 (通常不超過 10s),
並用一個 索引檔 (index file) 記錄這些小檔案的順序與位址,即 — .M3U8 檔
 
HLS
[註]:HLS 並非 real-time delivery system
 


 

M3U8

.M3U8 是一種 UTF-8 編碼的 M3U 擴充,簡單來說:

就是一種 播放列表 (playlist)

 
一個簡易的 .M3U8 檔範例:

#EXT-X-VERSION:3
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:1

#EXTINF:10.0,
https://media.example.com/segment1.ts
#EXTINF:9.5,
https://media.example.com/segment2.ts
#EXT-X-ENDLIST

 
客戶端 (Client) 透過某 URL 取得 .M3U8 後,
便能依進度對其中的 小媒體 .ts 發送請求 😆。
(全部的 .ts 合起來,就是完整的影片囉)
 


 

FFMPEG

有了以上基本知識,便能開始下載囉!
其基本概念就是:

  1. 獲取 .m3u8 檔
  2. 依照 .m3u8,依序取得其中的 .ts
  3. 將多個 .ts 合併為單一媒體

 
放心,實際上真正需要動手的只有第一步驟,
第二與第三步驟,霸道的 FFmpeg 幫我們做好了!

 


 

下載 FFmpeg

首先,先著手安裝 FFmpeg 吧!
使用 Mac 的朋友,可以使用 Homebrew 一鍵完成:

brew install ffmpeg

 
若您是 Windows 平台,則可以去 官網 下載,
當然,若您想直接作為可執行檔使用,不想另外自行編譯,
請選擇 Windows Package 的 Windows Builds:

 
接著,下載對映架構的 靜態編譯 (Static Build):

 
下載完成後,便解壓縮到一個喜歡的地方吧 😃,
這裡以 C 槽的 Program Files 為例,並命名目錄為 ffmpeg:

 
欸~ 先別急著關閉視窗!請先複製底下 bin 資料夾的路徑,例如:

C:\Program Files\ffmpeg\bin

 


 

設置 PATH

為了便於使用,接下來要設置環境變數 $PATH
使用 Mac 的朋友什麼都不用做,Homebrew 幫你鏈結完成了 😆。
 
而使用 Windows 的話,則在『本機』點擊右鍵,進入『內容』,
接著『進階系統設定』->『環境變數』-> 找到(或新增) Path 變數,
將剛剛複製的 bin 路徑貼上,即可保存離開:
win-path-setting
 


 

檢查版本

安裝與設置已經大功告成囉,打開一個『新的』終端機測試看看吧!
使用 Mac 的朋友,可以叫 siri 幫你開 😂:
siri-terminal
 
使用 Windows 的話,則搜尋 cmd,打開命令提示字元:
win-cmd
 
接著輸入:

ffmpeg -version

若出現以下類似畫面便代表成功囉!

 
 
若出現「找不到命令」,排除您 $Path 設置錯誤,
則通常是新環境變數尚未生效,最簡單的解法就是重新啟動囉!
 


 

下載 M3U8

環境設置完成後,就開始尋找 .m3u8 播放清單吧,
這部分可利用 Browser 的 開發者工具 輕易達成!
 
隨便開啟一個分頁後,按 F12ctrl+shift+i 招喚他吧!

 
接下來,前往你想下載的影片網站吧 (請先確認該網站是採用 hls 😂)!
進入 開發者工具的 網路 (Network) 分頁後,輸入 m3u8 過濾掉垃圾:

 
點擊右鍵,複製該網址,開啟終端機,輸入以下指令 🧙‍♂️:

ffmpeg -protocol_whitelist "file,http,https,tcp,tls" \
-i "將m3u8網址貼上到這邊" \
-c copy "你想儲存的檔案路徑/test.mp4"

 
以 Windows 路徑為例 (Windows 換行符需更換為 ^):

ffmpeg -protocol_whitelist "file,http,https,tcp,tls" ^
-i "https://xxx.xxx/m3u8" ^
-c copy "C:\Users\Jason\Desktop\test.mp4"

 
一般影片即可下載完成!
 
[註]:-i 參數意指 input; -c 參數意指 codec
 


 

Troubleshooting

然而,也是有可能下指令後出現錯誤 (假設路徑設置正確),
這通常是因為 .M3U8 或 底下的 .ts 有受到防護
可能是 HTTP 的 Referer 也或者是 CSRF Token…等。
 
以下提供兩種解決方案:
 

儲存 m3u8 為本地文件

首先,找個地方建立一個『xxx.m3u8』文字檔案:
(若有 txt 要記得去掉喔 😄)

 
將開發者工具的『回應內容』直接複製貼上後存檔:

 
最後,將 -i 參數 (input) 的對象,改為該檔案路徑,例如:

ffmpeg -protocol_whitelist "file,http,https,tcp,tls" \
-i "C:\Users\Jason\Desktop\test.m3u8" \
-c copy "C:\Users\Jason\Desktop\test.mp4"

註:Windows 系統需將 換行符 (\) 更換為 ^
 
此種做法較簡單但不可靠,適用於:

Server 未對 .ts 做進一步防護。

 


 

設置 HTTP 表頭

許多網站會透過 User-Agent, Origin, Referer, 甚至 Cookie 等表頭進行簡易的存取認證,
此時可透過 FFMPEG 的 -user_agent-headers 等參數偽造 HTTP 表頭。
 
首先,透過「開發者工具」->「網路」找到目標 m3u8 檔,並將其連結填入 -i 參數中,
先別急著關閉視窗!去找到請求表/檔頭區塊:

 
分別將 User-Agent 填入 -user_agent 參數,其他「可疑」表頭填入 -headers 參數:
其中,-headers 的參數值格式建議為 (僅適用於 macOS, Linux 等作業系統):

$'表頭1: 值\r\n表頭2: 值\r\n'

 
例如:

ffmpeg -protocol_whitelist "file,http,https,tcp,tls" \
-user_agent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0" \
-headers $'Origin: origin表頭值\r\nReferer: referer表頭值\r\nCookie: cookie值\r\n' \
-i "http://xxx.yyy/zzz.mp4/index.m3u8" \
-c copy "/Users/Jason/Desktop/example.mp4"

 
通常透過此法即可下載絕大多數的 m3u8 影音,
若不成功,就得想辦法獲取 Token, 網站授權…等 😄。
 
然而,Windows 作業系統的 命令提示字元 並不支援 $' ' 字串,使用此法將會造成錯誤!
解決方式很多,例如使用「適用於 Linux 的 Windows 子系統」,
或透過其他語言處理表頭字串再執行 FFMPEG。
 
以 Python 為例:

from subprocess import call

call(["ffmpeg",
      "-protocol_whitelist", proWhitelist,
      "-user_agent", userAgent,
      "-headers", headers,
      "-i", url,
      "-c", codec,
      outputUrl])

 
以 Java 為例:

ProcessBuilder processBuilder = new ProcessBuilder("ffmpeg",
        "-v", v,
        "-protocol_whitelist", protocol_whitelist,
        "-user_agent", user_agent,
        "-headers", headers,
        "-i", i,
        "-c", c,
        output_url);
Process p = processBuilder.start();

 
 

作者: 鄭中勝
喜愛音樂,但不知為何總在打程式 ? 期許能重新審視、整理自身所學,幫助有需要的人。

在《M3U8 串流影音 — 概念 與 下載》中有 24 則留言

  1. 請問某網站出現 Server returned 403 Forbidden (access denied)
    這有解嗎? 我用最後的方法
    另外 以上語法貌似是在MAC下的格式 CMD下有點不同

    1. 這是因為 Windows 沒有 $’ ‘ 字串喔!
      因此 HTTP 表頭並未設定成功
      可透過 C 或 Java…等處理表頭字串
      並代為執行 ffmpeg 😃

          1. 所以勝哥有tool 了嗎:D,
            還是windows 有什麼方法可以解決access denied這個問題

  2. call([“ffmpeg”,
    “-protocol_whitelist”, proWhitelist,
    “-user_agent”, userAgent,
    “-headers”, headers,
    “-i”, url,
    “-c”, codec,
    outputUrl])

    請問以上的 (“-c”, codec, ) codec 要填什麼才對呢? 這裡的codec是什麼意思呢?

    1. 可以直接填入 copy 即可喔!
      codec 是指 編碼器與解碼器 (encoder and decoder)

  3. 個別的TS檔網址出現403 forbidden 是因為也有檢查cookie嗎? 還是TS有寫入保護?

  4. 請問一下,用儲存本地檔案的方式cmd跑完後顯示:
    Error when loading first segment ‘http://xxx.ts’
    C:\Users\Tofu\Desktop\test.m3u8: Invalid data found when processing input
    是哪裡有錯誤呢??

  5. 把ffmpeg加到Path之後,
    windows檢查ffmpeg有沒有安裝成功那裡,要用系統管理員身份執行cmd,不然Windows會擋下來,然後裝傻跟你說不知道ffmpeg是什麼….

  6. 根据您的方法成功提取视频了!十分简单易懂的教程,真的十分感谢^_^

  7. 請問如果Unable to open key file 類似這種訊息 要如何處理呢?
    有用過VDH試過同個網站 好像抱錯ERROR ABORTED

  8. C:\ffmpeg\bin>ffmpeg -protocol_whitelist “file,http,https,tcp,tls” ^
    More? -i “https://hls.hydrax.net/7UA17cpVS9ThW81tleYuEzjTD8TjVz9PWtX4EaAxLSOxLUsqLaO/0/2f7064ca5dc2f4060b146d57a149cb17.m3u8” ^
    More? -c copy “xxx.mp4”
    ffmpeg version N-93825-gc967128952 Copyright (c) 2000-2019 the FFmpeg developers
    built with gcc 8.3.1 (GCC) 20190414
    configuration: –enable-gpl –enable-version3 –enable-sdl2 –enable-fontconfig –enable-gnutls –enable-iconv –enable-libass –enable-libdav1d –enable-libbluray –enable-libfreetype –enable-libmp3lame –enable-libopencore-amrnb –enable-libopencore-amrwb –enable-libopenjpeg –enable-libopus –enable-libshine –enable-libsnappy –enable-libsoxr –enable-libtheora –enable-libtwolame –enable-libvpx –enable-libwavpack –enable-libwebp –enable-libx264 –enable-libx265 –enable-libxml2 –enable-libzimg –enable-lzma –enable-zlib –enable-gmp –enable-libvidstab –enable-libvorbis –enable-libvo-amrwbenc –enable-libmysofa –enable-libspeex –enable-libxvid –enable-libaom –enable-libmfx –enable-amf –enable-ffnvcodec –enable-cuvid –enable-d3d11va –enable-nvenc –enable-nvdec –enable-dxva2 –enable-avisynth –enable-libopenmpt
    libavutil 56. 26.101 / 56. 26.101
    libavcodec 58. 52.101 / 58. 52.101
    libavformat 58. 27.103 / 58. 27.103
    libavdevice 58. 7.100 / 58. 7.100
    libavfilter 7. 50.100 / 7. 50.100
    libswscale 5. 4.100 / 5. 4.100
    libswresample 3. 4.100 / 3. 4.100
    libpostproc 55. 4.100 / 55. 4.100
    [https @ 000002a70fe3a0c0] HTTP error 404 Not Found
    https://hls.hydrax.net/7UA17cpVS9ThW81tleYuEzjTD8TjVz9PWtX4EaAxLSOxLUsqLaO/0/2f7064ca5dc2f4060b146d57a149cb17.m3u8: Server returned 404 Not Found

    C:\ffmpeg\bin>

    [https @ 000002a70fe3a0c0] HTTP error 404 Not Found ? ? ?
    Please help

  9. 身為Linux的用戶一定要給你大大的讚,太詳細了
    也很好除錯,感謝大大提供,如果大大也是熱愛寫程式的人可以與我聯絡討論哦

  10. 不好意思,請問我在環境變數的使用者變數中只有看到TEMP而沒有其他的,但系統變數中有PATH,請問我是要在下方的系統變數的PATH中新增嗎?感謝你~

發表迴響