php獲取hls流媒體信息需先解析.m3u8文件。1. 使用file_get_contents()讀取m3u8文件內容;2. 通過explode()逐行解析文本;3. 提取關鍵標簽如#ext-x-version、#ext-x-media-sequence、#ext-x-targetduration及#extinf等;4. 處理相對url轉換為絕對路徑;5. 若存在aes-128加密,解析#ext-x-key獲取密鑰url并解密媒體片段;6. 針對多碼率流,識別#ext-x-stream-inf標簽并遞歸解析不同碼率的m3u8文件;7. 性能優化方面采用流式讀取、正則表達式優化、緩存解析結果及高效字符串處理函數以提升效率。
PHP獲取HLS流媒體信息,核心在于解析HLS的索引文件(.m3u8文件)。這文件里包含了視頻分片和其他必要信息,我們可以用PHP讀取并處理它。
解決方案:
- 讀取M3U8文件內容
使用file_get_contents()函數讀取M3U8文件的URL,將其內容保存到字符串中。
立即學習“PHP免費學習筆記(深入)”;
<?php $m3u8_url = 'YOUR_M3U8_URL'; $m3u8_content = file_get_contents($m3u8_url); if ($m3u8_content === false) { die('Failed to fetch M3U8 file.'); } // 現在 $m3u8_content 包含了 M3U8 文件的內容 ?>
- 解析M3U8內容
M3U8文件是文本文件,我們需要逐行解析。使用explode()函數按行分割字符串。
<?php $lines = explode("n", $m3u8_content); ?>
- 提取關鍵信息
遍歷每一行,根據M3U8文件的格式提取信息。常見的標簽包括:
- #EXTM3U: 文件頭,表示這是一個M3U8文件。
- #EXT-X-VERSION: HLS協議版本。
- #EXT-X-MEDIA-SEQUENCE: 第一個媒體片段的序列號。
- #EXT-X-TARGETDURATION: 每個媒體片段的目標持續時間(秒)。
- #EXTINF: 媒體片段的信息,包括持續時間和文件名。
- #EXT-X-ENDLIST: 表示流的結束。
<?php $version = null; $media_sequence = null; $target_duration = null; $segments = []; foreach ($lines as $line) { $line = trim($line); // 去除空白 if (strpos($line, '#EXT-X-VERSION') === 0) { $version = intval(substr($line, strlen('#EXT-X-VERSION:'))); } elseif (strpos($line, '#EXT-X-MEDIA-SEQUENCE') === 0) { $media_sequence = intval(substr($line, strlen('#EXT-X-MEDIA-SEQUENCE:'))); } elseif (strpos($line, '#EXT-X-TARGETDURATION') === 0) { $target_duration = intval(substr($line, strlen('#EXT-X-TARGETDURATION:'))); } elseif (strpos($line, '#EXTINF') === 0) { // 獲取片段持續時間 preg_match('/EXTINF:([d.]+)/', $line, $matches); $duration = floatval($matches[1]); // 獲取片段文件名 (下一行) $segment_url = trim(next($lines)); $segments[] = ['duration' => $duration, 'url' => $segment_url]; } elseif (strpos($line, '#EXT-X-STREAM-INF') === 0) { //處理多碼率情況,提取不同碼率的url preg_match('/URI="([^"]+)"/', $line, $matches); if(isset($matches[1])){ $variant_url = $matches[1]; //這里可以遞歸調用這個函數,解析不同碼率的m3u8文件 } } } // 現在你可以使用這些信息了 var_dump($version, $media_sequence, $target_duration, $segments); ?>
- 處理相對URL
如果媒體片段的URL是相對路徑,需要將其轉換為絕對路徑。
<?php function makeAbsoluteUrl($base_url, $relative_url) { // 使用PHP內置函數處理 return SabreUriresolve($base_url, $relative_url); } $base_url = dirname($m3u8_url) . '/'; // M3U8文件所在的目錄 foreach ($segments as &$segment) { $segment['url'] = makeAbsoluteUrl($base_url, $segment['url']); } ?>
如何處理M3U8文件中的加密內容(如AES-128)?
M3U8文件中可能包含加密信息,例如使用AES-128加密。 遇到這種情況,你需要:
-
查找密鑰URL:M3U8文件中會有一個#EXT-X-KEY標簽,其中包含密鑰的URL。
#EXT-X-KEY:METHOD=AES-128,URI="YOUR_KEY_URL",IV=0x...
-
獲取密鑰:使用file_get_contents()從密鑰URL獲取密鑰。
<?php // 假設你已經獲取了密鑰和IV $key_url = 'YOUR_KEY_URL'; $key = file_get_contents($key_url); //IV 一般在EXT-X-KEY中指定,如果沒有,則默認為0 $iv = 'YOUR_IV'; // 使用 openssl 解密 $encrypted_data = file_get_contents('YOUR_ENCRYPTED_TS_FILE'); $decrypted_data = openssl_decrypt($encrypted_data, 'aes-128-cbc', $key, OPENSSL_RAW_DATA, $iv); if ($decrypted_data === false) { echo "解密失敗: " . openssl_error_string() . "n"; } else { // 保存解密后的數據 file_put_contents('YOUR_DECRYPTED_TS_FILE', $decrypted_data); } ?>
如何處理多碼率(Adaptive Bitrate Streaming)的M3U8文件?
多碼率HLS使用#EXT-X-STREAM-INF標簽來描述不同的碼率流。每個#EXT-X-STREAM-INF標簽后面跟著一個M3U8文件的URL,這個文件描述了特定碼率的流。
-
提取碼率信息:解析#EXT-X-STREAM-INF標簽,提取帶寬、分辨率等信息,以及對應的M3U8 URL。
-
選擇合適的碼率:根據網絡狀況和設備性能,選擇合適的碼率。
-
遞歸解析:下載并解析選定的M3U8文件,獲取媒體片段信息。
<?php // 在主循環中,處理 #EXT-X-STREAM-INF elseif (strpos($line, '#EXT-X-STREAM-INF') === 0) { preg_match('/BANDWIDTH=(d+),.*URI="([^"]+)"/', $line, $matches); $bandwidth = intval($matches[1]); $variant_url = trim($matches[2]); // 遞歸調用函數,解析不同碼率的m3u8文件 $variant_data = parseM3U8($variant_url); $variants[] = ['bandwidth' => $bandwidth, 'url' => $variant_url, 'data' => $variant_data]; } //輔助函數,遞歸解析不同碼率的m3u8文件 function parseM3U8($url){ $m3u8_content = file_get_contents($url); //... 這里可以復用之前的解析邏輯 return $m3u8_content; } ?>