著者 | Liu Bo (Paiyun マルチメディア開発エンジニアでもある)
現在、モバイル Web でのライブ ブロードキャストに対する比較的熱い需要に応えるために、一連の HTML5 ライブ ブロードキャスト テクノロジが急速に開発されています。
HTML5 で使用できる一般的なライブ ストリーミング テクノロジーには、HLS、WebSocket、WebRTC などがあります。今回はWebSocketとMSEに関する技術的なポイントを紹介し、最後に具体的な使い方を例を挙げて説明します。
WebSocketプロトコルの紹介
WebSocketクライアント/サーバーAPIの紹介
MSEの紹介
fMP4の紹介
デモ展示
通常のWebアプリケーションこれらはすべて HTTP リクエスト/レスポンス モデルを中心に構築されています。すべての HTTP 通信はクライアントを通じて制御され、サーバーはリクエストを受信して処理した後、結果をクライアントに返し、クライアントはデータを表示します。このモードではリアルタイム アプリケーションのニーズを満たすことができないため、SSE や Comet などの「サーバー プッシュ」長時間接続テクノロジが登場しました。
WebSocketはTCPコネクションをベースとした通信プロトコルであり、単一のTCPコネクション上で全二重通信を行うことができます。 WebSocket は、2011 年に IETF によって標準 RFC 6455 として設定され、RFC 7936 によって補足されました。WebSocket API は、W3C によって標準として設定されました。
WebSocket は TCP 上で独自に作成されたプロトコルです。HTTP プロトコルの概念は WebSocket とは関係ありません。唯一関連するのは、プロトコル スイッチングに HTTP プロトコルの 101 ステータス コードを使用する場合、使用される TCP ポートは 80 であることです。ほとんどのファイアウォールの制限を回避できます。
新しいプロトコルの展開を容易にするために、HTTP/1.1 ではアップグレード メカニズムが導入されました。これにより、クライアントとサーバーは既存の HTTP 構文を使用して他のプロトコルにアップグレードできます。このメカニズムについては、RFC7230 のセクション 6.7 アップグレードで詳しく説明されています。
HTTP/1.1 プロトコルのアップグレードを開始するには、クライアントはリクエスト ヘッダーでこれら 2 つのフィールドを指定する必要があります ▽
> Connection: Upgrade Upgrade: protocol-name[/protocol-version]
サーバーがアップグレードに同意する場合、次のように応答する必要があります ▽
> HTTP/1.1 101 Switching Protocols Connection: upgrade Upgrade: protocol-name[/protocol-version] [... data defined by new protocol ...]
これまでに、HTTP アップグレード応答のステータス コードは 101 であり、応答本文では新しいプロトコルで定義されたデータ形式を使用できることがわかります。
WebSocket ハンドシェイクは、この HTTP アップグレード メカニズムを利用します。ハンドシェイクが完了すると、その後のデータ転送は TCP 経由で直接行われます。
現在主流のブラウザは、サーバーにメッセージ (テキストまたはバイナリ) を送信し、イベント駆動の応答データを受信できる WebSocket API インターフェイスを提供します。
ステップ1. ブラウザがWebSocketをサポートしているかどうかを確認します
> if(window.WebSocket) { // WebSocket代码 }
ステップ2. 接続を確立します
> var ws = new WebSocket('ws://localhost:8327');
ws.binaryType = 'arraybuffer';
WebSocket Golang API
サーバー側の WebSocket ライブラリについては、Google 独自の http://golang.org/x/net/websocket を使用することをお勧めします。これは net/http で非常に便利に使用できます。また、websocket.Handler を通じて WebSocket のハンドラー関数を http.Handler に変換して、net/http ライブラリーで使用できるようにすることもできます。
次に、websocket.Message.Receive を通じてデータを受信し、websocket.Message.Send を通じてデータを送信します。
特定のコードについては、以下のデモセクションをご覧ください。
MSE を紹介する前に、まず HTML5
HTML5
ストリーミングのサポートなし
DRM と暗号化のサポートなし
コントロールのカスタマイズとブラウザ間での一貫性の維持が困難
エンコーディングカプセル化とカプセル化はブラウザごとにサポート方法が異なります
MSE は HTML5 のストリーミング問題を解決するものです。
Media Source Extensions (MSE) は、Chrome、Safari、Edge などの主流のブラウザーでサポートされる新しい Web API です。 MSE は、JavaScript が
MSE を使用すると、プラグインを必要とせずにメディア ストリームを動的に変更できます。これにより、フロントエンド JavaScript は、JavaScript での再パッケージ化、処理、さらにはトランスコーディングなど、より多くのことを実行できるようになります。
MSE はストリームをメディア タグに直接送信できませんが、MSE はクロスブラウザ プレーヤーを構築するためのコア テクノロジーを提供し、ブラウザが JavaScript API を通じてオーディオとビデオをメディア タグにプッシュできるようにします。
ブラウザがサポートしているかどうかを確認するには、caniuse を使用します。
MediaSource.isTypeSupported() を通じて、コーデックの MIME タイプがサポートされているかどうかをさらに確認できます。
より一般的に使用されるビデオ パッケージ形式は、WebM と fMP4 です。
WebM と WebP は 2 つの姉妹プロジェクトであり、どちらも Google がスポンサーとなっています。 WebM は Matroska に基づくコンテナ形式であるため、本質的にストリーミングであり、ストリーミング メディアの分野での使用に非常に適しています。
以下は fMP4 形式に焦点を当てます。
MP4 が一連のボックスで構成されていることは誰もが知っています。通常の MP4 は入れ子構造になっており、完全に再生するにはクライアントが MP4 ファイルを最初からロードする必要があり、途中から再生を開始することはできません。
そして、fMP4 は一連のフラグメントで構成されています。サーバーがバイト範囲リクエストをサポートしている場合、ファイル全体をロードせずに、これらのフラグメントをクライアントに個別にリクエストして再生することができます。
この点をより明確に説明するために、MP4 ファイルを分析するために一般的に使用されるいくつかのツールを以下に紹介します。
gpac (以前は mp4box として知られていました) は、ソース コードの下に多数のメディア分析ツールがあり、
mp4box.js は mp4box の Javascript バージョンです。 ;
bento4、MP4 専用の分析ツール;
mp4parser、オンライン MP4 ファイル分析ツール。
以下は、mp4parser (オンラインMPEG4パーサー)によって分析されたフラグメントmp4ファイルのスクリーンショットです ▽
以下は、分析された非フラグメントmp4ファイルのスクリーンショットですby mp4parser ▽
非フラグメント mp4 にはトップレベル ボックス タイプがほとんどなく、フラグメント mp4 は moof+mdat セグメントで構成されており、それらにはすでに十分なメタデータ情報とデータが含まれており、直接シークできることがわかります。この位置に移動してプレイを開始します。言い換えれば、fMP4 はストリーミング カプセル化形式であり、ファイル ヘッダーのメタデータに依存せずにネットワーク上でストリーミングするのに適しています。
Apple は WWDC 2016 カンファレンスで、iOS 10、tvOS、macOS の HLS で fMP4 をサポートすると発表しました。これは、fMP4 の見通しが非常に良好であることを示しています。
fMP4、CMAF、ISOBMFF は実際には似たものであることに言及する価値があります。
MSE JavaScript API
概要では、MSE は
メディア ストリームを構築するための JavaScript API
スプライシングおよびキャッシング モデル
いくつかのバイト ストリーム タイプを識別します
WebM
ISO ベースメディアファイル形式
MPEG-2 トランスポートストリーム
MSE 本身的设计是不依赖任务特定的编解码和容器格式的,但是不同的浏览器支持程度是不一样的。
可以通过传递一个 MIME 类型的字符串到静态方法:
> MediaSource.isTypeSupported来检查。比如 ▽ MediaSource.isTypeSupported('audio/mp3'); // false MediaSource.isTypeSupported('video/mp4'); // true MediaSource.isTypeSupported('video/mp4; codecs="avc1.4D4028, mp4a.40.2"'); // true
获取 Codec MIME string 的方法可以通过在线的 [mp4info](http://nickdesaulniers.github.io/mp4info),或者使用命令行 mp4info test.mp4 | grep Codecs,可以得到类似如下结果 ▽
> mp4info fmp4.mp4| grep Codec Codecs String: mp4a.40.2 Codecs String: avc1.42E01E
当前,H.264 + AAC 的 MP4 容器在所有的浏览器都支持。
普通的 MP4 文件是不能和 MSE 一起使用的, 需要将 MP4 进行 fragment 化。
检查一个 MP4 是否已经 fragment 的方法 ▽
> mp4dump test.mp4 | grep "\[m"
如果是non-fragment会显示如下信息 ▽
> mp4dump nfmp4.mp4 | grep "\[m" [mdat] size=8+50873 [moov] size=8+7804 [mvhd] size=12+96 [mdia] size=8+3335 [mdhd] size=12+20 [minf] size=8+3250 [mdia] size=8+3975 [mdhd] size=12+20 [minf] size=8+3890 [mp4a] size=8+82 [meta] size=12+78
如果已经 fragment,会显示如下的类似信息 ▽
> mp4dump fmp4.mp4 | grep "\[m" | head -n 30 [moov] size=8+1871 [mvhd] size=12+96 [mdia] size=8+312 [mdhd] size=12+20 [minf] size=8+219 [mp4a] size=8+67 [mdia] size=8+371 [mdhd] size=12+20 [minf] size=8+278 [mdia] size=8+248 [mdhd] size=12+20 [minf] size=8+156 [mdia] size=8+248 [mdhd] size=12+20 [minf] size=8+156 [mvex] size=8+144 [mehd] size=12+4 [moof] size=8+600 [mfhd] size=12+4 [mdat] size=8+138679 [moof] size=8+536 [mfhd] size=12+4 [mdat] size=8+24490 [moof] size=8+592 [mfhd] size=12+4 [mdat] size=8+14444 [moof] size=8+312 [mfhd] size=12+4 [mdat] size=8+1840 [moof] size=8+600
把一个 non-fragment MP4 转换成 fragment MP4。
可以使用 FFmpeg 的 -movflags 来转换。
对于原始文件为非 MP4 文件 ▽
> ffmpeg -i trailer_1080p.mov -c:v copy -c:a copy -movflags frag_keyframe+empty_moov bunny_fragmented.mp4
对于原始文件已经是 MP4 文件 ▽
> ffmpeg -i non_fragmented.mp4 -movflags frag_keyframe+empty_moov fragmented.mp4
或者使用 mp4fragment ▽
> mp4fragment input.mp4 output.mp4
DEMO TIME
最后阶段,展示两个demo,分别是 MSE Vod Demo、MSE Live Demo
MSE Vod Demo
展示利用 MSE 和 WebSocket 实现一个点播服务
后端读取一个 fMP4 文件,通过 WebSocket 发送给 MSE,进行播放
展示利用 MSE 和 WebSocket 实现一个直播服务
后端代理一条 HTTP-FLV 直播流,通过 WebSocket 发送给 MSE,进行播放
前端 MSE 部分做了很多工作, 包括将 flv 实时转封装成了 fMP4,这里引用了 videojs-flow 的实现
Refs
WebSocket
rfc6455
HTTP Upgrade
WebSocket API
MDN WebSocket
videojs-flow
MSE
W3C
MDN MSE
HTML5 Codec MIME
又拍直播云是基于又拍云内容分发网络为直播应用提供超低延迟、高码率、高并发的整套从推流端到播放端的一站式解决方案。包括实时转码,实时录制,分发加速,水印,截图,秒级禁播,延时直播等功能。直播源站支持自主源站或又拍云源,为支持用户在不同终端播放,支持 RTMP、HLS、HTTP-flv 播放输出。
详情了解:https://www.upyun.com/products/live
推荐阅读:
无连麦,不直播,都在说的直播利器连麦互动到底是啥?
技术干货|移动直播六大关键技术详解
又拍直播云SDK,自带美颜、滤镜、消噪、人声增益等功能
又拍直播云功能处理篇:转码、录制、视频水印、视频截图
又拍直播云功能基础篇:推流和拉流、多协议输出、多访问方式、回源端口自定义
又拍直播云功能高级篇:防盗链、秒级禁播、自动鉴黄、API接口
以上がWebSocket+MSE——HTML5ライブブロードキャスト技術の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。