搜尋
首頁web前端H5教程flv.js怎麼用?全面解讀flv.js程式碼

    首先聲明,我不太懂JavaScript,我只是熟悉音視頻處理部分,有錯誤在所難免,歡迎指正。

flv.js專案的程式碼有一定規模,如果要研究的話,我建議從demux入手,理解了demux就掌握了媒體資料處理的關鍵步驟,前面的媒體數據下載和後面的媒體資料播放就變得容易理解了。

    先普及點背景知識,為什麼HTML5影片播放要用 flv 格式?

    因為Flash。我標題圖片用的是“flash RIP”,flash快死了,但是它的影響力還在,flash技術是過去10多年的互聯網視頻基礎技術,大量相關基礎設施都是圍繞Flash構建的,比如CDN 普遍支援的RTMP 和flv over http協定。做網路直播的公司為了能相容於Web上的Flash播放,不約而同地選擇了flv的媒體格式。在從Flash到 HTML5過渡的時期,如果HTML5能支援flash的協定是再好不過了,可以平滑過渡,然而HTML5並不原生支援flash協定。 flv.js這個計畫解決了HTML5支援flash協議的問題,這就是flv.js應運而生短期爆紅的歷史背景。

    flv.js 中的demux就是一套 FLV 媒體資料格式的解析器,如果要理解FLV格式,下面的文件是必須熟讀的。
Adobe官方的flv格式說明
http://www.adobe.com/content/dam/Adobe/en/devnet/flv/pdfs/video_file_format_spec_v10.pdf

#   flv. js怎麼用? 下面進入正題,flv.js程式碼解讀:demux部分

    開啟程式碼 https://github.com/Bilibili/flv.js/blob/master/src/demux/flv-demuxer.js

 static probe(buffer) {
        let data = new Uint8Array(buffer);
        let mismatch = {match: false};

        if (data[0] !== 0x46 || data[1] !== 0x4C || data[2] !== 0x56 || data[3] !== 0x01) {
            return mismatch;
        }

    0x46 0x4c 0x56 這幾個數字其實就是 'F' 'L' 'V' 的ascii碼,表示flv檔頭,後面的0x01是flv格式的版本號,用這來偵測資料是不是 flv 格式。

let hasAudio = ((data[4] & 4) >>> 2) !== 0;
let hasVideo = (data[4] & 1) !== 0;

    取出第五個字節,它的第六 和 第八 bit 分別表示是否存在 音訊和視訊數據,其它位是保留位可以忽略。

    這個probe是被 parseChunks 調用的,當讀取了至少13個位元組後,就判斷下是否是一個flv數據,然後再繼續後面的分析。為什麼是13,因為flv的文件頭就是13個字節,參考上面PDF裡的“The FLV header”,這13個字節包括了後面的一個四字節的size,這個size表示前一個tag的大小,但是由於第一個tag是不存在前一個的,所以第一個size總是0。

    parseChunks 後面的程式碼就是在不斷解析tag,flv把一段媒體資料稱為TAG,每個tag有不同的type,實際上真正用到的只有三種type,8、9、18 分別對應,音訊、視訊和Script Data。

 if (tagType !== 8 && tagType !== 9 && tagType !== 18) {
                Log.w(this.TAG, `Unsupported tag type ${tagType}, skipped`);
                // consume the whole tag (skip it)
                offset += 11 + dataSize + 4;
                continue;
            }

    這段程式碼就在判斷tag type,注意看 那個 數字 11,因為tag header是11個位元組,後面就是tag body了,所以offset加上這些偏移是為了跳到下一個tag的位置。

    tag header的格式為:UI 表示 unsigned int,後面的是bit數。

UI8 tag type
UI24 data size
UI24 timestamp
UI8 TimestampExtended
UI24 StreamID

    你看是不是正好11 個字節,adobe為了節約流量,能用24bit表示的絕不用32bit,但是還是給timestamp設置了一個擴展位存放最高位的字節,這個設計很蛋疼,於是導致了下面這段奇葩程式碼,先取三個位元組依照Big-Endian轉換成整數再在高位放上第四個位元組。

let ts2 = v.getUint8(4);
let ts1 = v.getUint8(5);
let ts0 = v.getUint8(6);
let ts3 = v.getUint8(7);
let timestamp = ts0 | (ts1 << 8) | (ts2 << 16) | (ts3 << 24);

    解析完了 tag header後面分別依照不同的 tag type呼叫不同的解析函數。

switch (tagType) {
    case 8:  // Audio
        this._parseAudioData(chunk, dataOffset, dataSize, timestamp);
        break;
    case 9:  // Video
        this._parseVideoData(chunk, dataOffset, dataSize, timestamp, byteStart + offset);
        break;
    case 18:  // ScriptDataObject
        this._parseScriptData(chunk, dataOffset, dataSize);
        break;
}

TAG type:8 音訊

    音訊結構比較簡單,AUDIODATA的第一個位元組表示音訊格式,其實基本上都是ACC 16bit 立體聲44.1kHz取樣,所以最常見的數字就是0xAF,後面一般就是AACAUDIODATA了

TAG type : 9 影片

    重點看的是視頻,

let frameType = (spec & 240) >>> 4;
let codecId = spec & 15;

    這裡取兩個重要的值,frameType表示幀類型 1 是關鍵幀 2 是非關鍵幀,codeId是編碼類型。雖然flv支援 六種視訊格式,但實際上網路點播直播真正在用的基本只有H.264一種。所以codecId基本上都是7。這裡作者用了十進制的數,其實就是按位取值,用16進制的數會更好理解。

    _parseAVCVideoPacket 用來解析 AVCVIDEOPACKET 結構,就是H.264的視訊包

let packetType = v.getUint8(0);
let cts = v.getUint32(0, !le) & 0x00FFFFFF;

    解釋下CTS的概念,CompositionTime,我們前面在tag header裡拿到過一個timestamp,這個在影片裡對應DTS,就是解碼時間戳,而CTS其實是一個offset,表示PTS相對於DTS的偏移量,就是PTS和DTS的差值。

    这里有个坑,参考adobe的文档,这是CTS是个有符号的24位整数,SI24,就是说它有可能是个负数,所以我怀疑flv.js解析cts的代码有bug,没有处理负数情况。因为负数的24位整型到32位负数转换的时候要手工处理高位的符号位和补码问题。(我只是怀疑,没有调试确认过,但是我在处理YY直播数据的时候是踩过这个坑的,个别包含 B frame的视频是会出现CTS为负数的情况的)

flv.js怎麼用?全面解讀flv.js程式碼


    packetType有两种,0 表示 AVCDecoderConfigurationRecord,这个是H.264的视频信息头,包含了 sps 和 pps,AVCDecoderConfigurationRecord的格式不是flv定义的,而是264标准定义的,如果用ffmpeg去解码,这个结构可以直接放到 codec的extradata里送给ffmpeg去解释。

    flv.js作者选择了自己来解析这个数据结构,也是迫不得已,因为JS环境下没有ffmpeg,解析这个结构主要是为了提取 sps和pps。虽然理论上sps允许有多个,但其实一般就一个。

let config = SPSParser.parseSPS(sps);

    pps的信息没什么用,所以作者只实现了sps的分析器,说明作者下了很大功夫去学习264的标准,其中的Golomb解码还是挺复杂的,能解对不容易,我在PC和手机平台都是用ffmpeg去解析的。SPS里面包括了视频分辨率,帧率,profile level等视频重要信息。

    packetTtype 为 1 表示 NALU,NALU= network abstract layer unit,这是H.264的概念,网络抽象层数据单元,其实简单理解就是一帧视频数据。

    NALU的头有两种标准,一种是用 00 00 00 01四个字节开头这叫 start code,另一个叫mp4风格以Big-endian的四字节size开头,flv用了后一种,而我们在H.264的裸流里常见的是前一种。

TAG type : 18 Script Data

    除了音视频数据外还有 ScriptData,这是一种类似二进制json的对象描述数据格式,JavaScript比较惨只能自己写实现,其它平台可以用 librtmp的代码去做。

    我觉得作者处理解决flv播放问题外,也为前端贡献了 amf 解析,sps解析,Golomb解码等基础代码,这些是可以用在其他项目里的。

    在用传输协议获取了flv数据流后,用demux分离出音视频数据的属性和数据包,这为后面的播放打下了基础,从demux入手去读代码是个不错的切入点,而且一定要配合 flv file format spec一起看,反复多看几遍争取熟记在心。我现在已经可以从wireshark的抓包数据里人肉分析flv数据包了,对于debug相当有帮助。

相关文章:

如何看待B站 (bilibili) 开源 HTML5 播放器内核 flv.js?

开源代码flv.js的使用说明

以上是flv.js怎麼用?全面解讀flv.js程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
HTML中的H5標籤是什麼?HTML中的H5標籤是什麼?May 09, 2025 am 12:11 AM

HTML中的H5標籤是第五級標題,用於標記較小的標題或子標題。 1)H5標籤幫助細化內容層次,提升可讀性和SEO。 2)結合CSS可定製樣式,增強視覺效果。 3)合理使用H5標籤,避免濫用,確保內容結構邏輯性。

H5代碼:Web結構的初學者指南H5代碼:Web結構的初學者指南May 08, 2025 am 12:15 AM

HTML5構建網站的方法包括:1.使用語義化標籤定義網頁結構,如、、等;2.嵌入多媒體內容,使用和標籤;3.應用表單驗證和本地存儲等高級功能。通過這些步驟,你可以創建一個結構清晰、功能豐富的現代網頁。

H5代碼結構:組織內容以實現可讀性H5代碼結構:組織內容以實現可讀性May 07, 2025 am 12:06 AM

通過合理的H5代碼結構可以讓頁面在眾多內容中脫穎而出。 1)使用語義化標籤如、、等組織內容,使結構清晰。 2)通過CSS佈局如Flexbox或Grid控制頁面在不同設備上的呈現效果。 3)實現響應式設計,確保頁面在不同屏幕尺寸上自適應。

H5與較舊的HTML版本:比較H5與較舊的HTML版本:比較May 06, 2025 am 12:09 AM

HTML5(H5)與舊版本HTML的主要區別包括:1)H5引入了語義化標籤,2)支持多媒體內容,3)提供離線存儲功能。 H5通過新標籤和API增強了網頁的功能和表現力,如和標籤,提高了用戶體驗和SEO效果,但需注意兼容性問題。

H5與HTML5:澄清術語和關係H5與HTML5:澄清術語和關係May 05, 2025 am 12:02 AM

H5和HTML5的區別在於:1)HTML5是網頁標準,定義結構和內容;2)H5是基於HTML5的移動網頁應用,適用於快速開發和營銷。

HTML5特徵:H5的核心HTML5特徵:H5的核心May 04, 2025 am 12:05 AM

HTML5的核心特性包括語義化標籤、多媒體支持、表單增強和離線存儲與本地存儲。 1.語義化標籤如、等提高了代碼可讀性和SEO效果。 2.多媒體支持通過和標籤簡化了嵌入媒體內容的過程。 3.表單增強引入了新的輸入類型和驗證屬性,簡化了表單開發。 4.離線存儲和本地存儲通過ApplicationCache和localStorage等提高了網頁性能和用戶體驗。

H5:探索最新版本的HTMLH5:探索最新版本的HTMLMay 03, 2025 am 12:14 AM

html5isamajorrevisionofthehtmlStandardThatRevolutionsWebDevelopmentBybyIntroDucingNewSemanticeLementSemelementsandAndCapabilities.1)itenhancesCodereAdabilityAndSeowitability andSeowithelientsLike,and.2)

超越基礎:H5代碼中的高級技術超越基礎:H5代碼中的高級技術May 02, 2025 am 12:03 AM

H5的高級技巧包括:1.利用進行複雜圖形繪製,2.使用WebWorkers提升性能,3.通過WebStorage增強用戶體驗,4.實現響應式設計,5.利用WebRTC實現實時通信,6.進行性能優化和最佳實踐。這些技巧幫助開發者構建更動態、互動和高效的Web應用。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)