目的 ¶
- 友人間等の少人数(最大5人程度)でWebベースで画面共有を行う
- VRChatのiwaSyncVideoに流す
既存手法の問題点 ¶
- Discord
- エンコーダが選べずCPUでエンコードされてしまう
- 画質やビットレート, 自由度に厳しい制限がある
- OBS / YouTube Live
- 最小遅延が6-7秒ほど (少し長い)
- 版権の自動判定が暴発し、「著作権侵害の申し立て」メールが来て悲しい
改善方針 ¶
- 第三者機関に動画を触らせない
- 再エンコード回避の為
- 版権自動判定等の回避の為
- WANをCDN等のサーバーを介さないため二度通さない
- 低レイテンシ化の為
尚、以下の恩恵に預かれなくなる。
- 音声等のメディアの版権の管理が行い易くなる
- 配信者側アップリンクが視聴者数に関わらず1
これらは画面共有を少人数で行うには、元より不要な機能である。
プロトコル選定 ¶
- RTMP
- FlashPlayer用のプロトコル
- TCPの接続若しくはそれをHTTPでラップした形の接続で有る為、煩雑さがある
- FlashPlayerを使わずに読む事が高難度
- iwaSyncVideoで読めなかった
- HTTP Live Streaming (HLS)
- m3u形式のプレイリストとぶつ切りにされた動画ファイルの単純な形式
- iwaSyncVideoで読める
- MPEG-DASH
- HLS的な物を標準化する動きにより生まれた
- iwaSyncVideoで読めない
今回、iwaSyncVideoとブラウザ上で正しく表示される事を目標としている為、比較的対応環境の多いHLSを採用した。
HLSとは ¶
以下がHLSのファイル構造である。
- s.m3u8
- s1.ts
- s2.ts
- s3.ts
- ...
m3u8のプレイリスト内には、以下の様な最新何件かのtsファイル名が書かれている。
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:5
#EXT-X-MEDIA-SEQUENCE:1710
#EXTINF:4.166667,
s1710.ts
#EXTINF:4.166667,
s1711.ts
#EXTINF:4.166667,
s1712.ts
#EXTINF:4.166667,
s1713.ts
#EXTINF:2.233333,
s1714.ts
#EXT-X-ENDLIST
クライアントは、この拡張されたm3u形式のプレイリストをポーリングし、書かれているファイル名のtsを連続でGET, 再生する。
これらのファイルにHTTPベースでアクセスできる環境を整えるだけで良い。
具体的な方法 ¶
映像ソースの自由度を担保するべく、OBSを主軸に扱う。
OBSの 設定
内の 出力
から 出力モード
を 基本
から 詳細
に変更すると、より詳細な設定が可能となる。
が、それでも 配信
の設定の自由度は低い為、 録画
の設定項目を使って配信用のファイルを作っていく。
種別
をカスタム出力 (ffmpeg)
にFFmpeg の出力の種類
をURLに出力
ファイルパス または URL
をWebサーバー配下に指定する。- 今回は
/home/user/public_html/s/s.m3u8
とした。 ファイルに出力
の場合ダイアログが出るが、特に変なことをしないURLに出力
を選んだ
- 今回は
コンテナフォーマット
をhls
に映像ビットレート
を任意の値に3000kbps
にした
キーフレーム間隔
を任意の値に- 今回は2秒間隔の
120
とした (60fpsなので) - 短くすると低遅延/安定に成り易いが、容量が大きくなる
- 長くすると容量が小さくなるが、遅延増大/不安定になる
- 今回は2秒間隔の
映像エンコーダ
をlibx264
音声ビットレート
を任意の値に128kbps
にした
音声エンコーダ
をaac
これで、iwaSyncVideoに対してのストリームはm3u8へのURLで行える。
と、同時にWebベースでも見たい為同じディレクトリに以下のhtmlファイルを置いた。
<!DOCTYPE html>
<html lang=en>
<head>
<meta name=viewport content="width=device-width, initial-scale=1.0">
<title>Streaming</title>
<style>
html, body {
margin: 0;
width: 100%;
}
video {
width: 100%;
}
.container {
font-family: monospace;
max-width: 1280px;
margin: auto;
width: calc(100%-20px);
padding-left: 10px;
padding-right: 10px;
}
</style>
</head>
<body>
<script src=https://cdn.jsdelivr.net/npm/hls.js@latest></script>
<div class=container>
<h1>Streaming</h1>
<video id=video controls preload=none></video>
</div>
<script>
const video = document.getElementById('video');
if(Hls.isSupported()) {
const hls = new Hls();
hls.loadSource('s.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
}
</script>
</body>
</html>
結果的なレイテンシ ¶
運用してみた所、Webページから見た時、4-6秒程の遅延がある。
また、iwaSyncVideoからみると更に4-6秒程の遅延があった。
iwaSyncVideoから見るとレイテンシが増える問題はYouTube Liveでも同様である為、VRChat側の実装の問題と思われる。
やりたいことは大体できたため、今回はこれで良しとする。