要約すれば
FirefoxとChromeで動作させるのは簡単です。オーディオコーデックをコーデックリストに追加するだけです。 video/webm;codecs=opus,vp8
Safariで機能させるには、かなり複雑です。MediaRecorderは、開発者向けオプションの下で手動で有効にする必要がある「実験的」機能です。有効にすると、SafariにはisTypeSupported
メソッドがないため、それを処理する必要があります。最後に、MediaRecorderから何をリクエストしても、Safariは常に MP4ファイルを渡します。これは、WEBMのようにストリーミングすることはできません。つまり、ビデオコンテナーの形式をその場で変換するには、JavaScriptでトランスマックスを実行する必要があります。
Chromeが動作すればAndroidは動作するはずです
iOSはMedia Source Extensionsをサポートしていないため、iOSではSourceBuffer
定義されておらず、ソリューション全体が機能しません
元の投稿
あなたが投稿したJSFiddleを見ると、始める前の簡単な修正が1つあります。
errorMsgElement
定義されていない変数を参照しています。<div>
ページに適切なIDを追加し、const errorMsgElement = document.querySelector(...)
それをキャプチャするための行を作成する必要があります
Media Source ExtensionsとMediaRecorderを使用するときに注意すべき点は、サポートがブラウザーごとに大きく異なることです。これはHTML5仕様の「標準化された」部分ですが、プラットフォーム間であまり一貫性がありません。私の経験では、MediaRecorderをFirefoxで動作させるのにそれほど労力はかかりません。Chromeで動作させることは少し難しく、Safariで動作させることはほぼ不可能であり、iOSで動作させることは文字通り不可能ですあなたができる何か。
ブラウザごとにこれを実行してデバッグし、私の手順を記録して、メディアの問題をデバッグするときに使用できるツールの一部を理解できるようにしました
Firefox
FirefoxでJSFiddleをチェックアウトすると、コンソールに次のエラーが表示されました。
NotSupportedError:オーディオトラックを記録できません:video / webm; codecs = vp8はサポートされていないコーデックを示します
VP8 / VP9はGoogleによる大きなプッシュであり、Firefoxでは機能しない可能性があることを思い出したので、コードを少し調整しました。への, options)
呼び出しからパラメータを削除しましたnew MediaRecorder()
。これはおそらく、すべてのブラウザで異なる出力を取得します(それは、少なくともする必要がありますので、それは、望んでいるものは何でもコーデックを使用するブラウザに指示作品すべてのブラウザで)
これはFirefoxで機能したため、Chromeをチェックアウトしました。
クロム
今回は新しいエラーが発生しました:
(インデックス):409キャッチされていません(約束どおり)DOMException: 'SourceBuffer'で 'appendBuffer'を実行できませんでした:このSourceBufferは親メディアソースから削除されました。MediaRecorder.handleDataAvailable(https://fiddle.jshell.net/43rm7258/1/show/:409:22)
だから私は私のブラウザーでchrome:// media-internals /に行き、これを見ました:
オーディオストリームコーデックのopusがSourceBufferコーデックと一致しません。
コードでは、ビデオコーデック(VP9またはVP8)を指定していますが、オーディオコーデックは指定していません。そのため、MediaRecorderは、ブラウザーに必要なオーディオコーデックを選択させます。デフォルトでは、ChromeのMediaRecorderはオーディオコーデックとして「opus」を選択しているように見えますが、ChromeのSourceBufferはデフォルトで別のものを選択します。これは簡単に修正されました。次のoptions.mimeType
ように設定した2行を更新しました。
options = { mimeType: "video/webm;codecs=opus, vp9" };
options = { mimeType: "video/webm;codecs=opus, vp8" };
options
MediaRecorderとSourceBufferの宣言に同じオブジェクトを使用するため、オーディオコーデックをリストに追加すると、SourceBufferが有効なオーディオコーデックで宣言され、ビデオが再生されます。
適切な対策として、Firefoxで新しいコード(オーディオコーデックを使用)をテストしました。これはうまくいった!したがって、options
リストにオーディオコーデックを追加するだけで(そしてMediaRecorderを宣言するためにパラメーターにそれを残すことで)、2対2 になります。
VP8とopusはFirefoxで動作するように見えますが、デフォルトではありません(Chromeとは異なり、MediaRecorderとSourceBufferのデフォルトは同じであるため、options
パラメーターを完全に削除すると機能します)
サファリ
今回は、処理できない可能性のあるエラーが発生しました。
未処理のPromise拒否:ReferenceError:変数が見つかりません:MediaRecorder
私が最初に行ったのは、この記事を取り上げたGoogle "Safari MediaRecorder" でした。やってみようかなと思って見てみました。案の定:
これをクリックしてMediaRecorderを有効にすると、コンソールで次のようになりました。
未処理のPromise拒否:TypeError:MediaRecorder.isTypeSupportedは関数ではありません。(「MediaRecorder.isTypeSupported(options.mimeType)」では、「MediaRecorder.isTypeSupported」は未定義です)
したがって、SafariにはisTypeSupported
メソッドがありません。心配する必要はありません。「このメソッドが存在しない場合は、Safariであると想定し、それに応じてタイプを設定します」
if (MediaRecorder.isTypeSupported) {
options = { mimeType: "video/webm;codecs=vp9" };
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = { mimeType: "video/webm;codecs=vp8" };
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = { mimeType: "video/webm" };
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = { mimeType: "" };
}
}
}
} else {
options = { mimeType: "" };
}
今、私はSafariがサポートするmimeTypeを見つける必要がありました。軽いグーグルはH.264がサポートされていることを示唆しているので、試してみました:
options = { mimeType: "video/webm;codecs=h264" };
これは私MediaRecorder started
に成功しましたがaddSourceBuffer
、新しいエラーで行で失敗しました:
NotSupportedError:この操作はサポートされていません。
私はこれをSafariで機能させる方法を試し、診断するつもりですが、今のところ私は少なくともFirefoxとChromeに対処しています
アップデート1
私はサファリに取り組み続けました。残念なことに、Safariにはメディアの内部を深く掘り下げるためのChromeとFirefoxのツールが欠けているため、多くの推測が行われます。
以前にを呼び出そうとすると、「操作はサポートされていません」というエラーが発生することがわかりましたaddSourceBuffer
。そこで、さまざまな状況でこのメソッドだけを呼び出して呼び出すための1回限りのページを作成しました。
play
ビデオで呼び出される前にソースバッファーを追加する
- メディアソースがビデオ要素にアタッチされる前にソースバッファーを追加する
- たぶん、異なるコーデックでソースバッファを追加します
- 等
問題はまだコーデックであり、許可されていない「操作」に関するエラーメッセージは少し誤解を招くことがわかりました。許可されなかったパラメーターです。MediaRecorderでは「h264」を指定するだけで機能しましたが、SourceBufferではコーデックパラメータを渡す必要がありました。
最初に試したのは、MDNサンプルページに移動し、そこで使用したコーデックをコピーすること'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
でした。これにより、同じ「許可されていない操作」エラーが発生しました。これらのコーデックのパラメータの意味を掘り下げる(一体何んのように42E01E
しても意味?)。私はもっと良い答えがあればいいのに、グーグルしながら、Safariでの使用について言及したこのStackOverflowの投稿を偶然見つけました'video/mp4; codecs="avc1.64000d,mp4a.40.2"'
。私はそれを試してみましたが、コンソールエラーはなくなりました!
コンソールエラーはなくなりましたが、まだビデオが表示されません。ですから、やるべきことはまだあります。
アップデート2
Safariのデバッガーでさらに調査(複数のブレークポイントを配置し、プロセスの各ステップで変数を検査)したところhandleDataAvailable
、Safariで呼び出されたことがないことがわかりました。FirefoxとChromeではmediaRecorder.start(100)
、仕様に従ってondatavailable
100ミリ秒ごとに正しく呼び出されるように見えますが、Safariはパラメーターを無視し、すべてを1つの大きなBlobにバッファーします。mediaRecorder.stop()
手動で呼び出すondataavailable
と、その時点までに記録されていたすべてのものが呼び出されます
を使用setInterval
しmediaRecorder.requestData()
て100ミリ秒ごとに呼び出しを試みましたrequestData
が、Safariで定義されていませんでした(どのようisTypeSupported
に定義されなかったかのように)。これは私を少し困らせました。
次に、MediaRecorderオブジェクト全体をクリーンアップし、100ミリ秒ごとに新しいオブジェクトを作成しようとしましたが、これにより行にエラーが発生しましたawait bufferedBlob.arrayBuffer()
。それが失敗した理由を私はまだ調査しています
アップデート3
MP4形式について覚えていることの1つは、コンテンツを再生するには「moov」アトムが必要であることです。これが、MP4ファイルの中央部分をダウンロードして再生できない理由です。WHOLEファイルをダウンロードする必要があります。それで、MP4を選択したのが定期的な更新を取得しなかった理由なのかと思いました。
video/mp4
いくつかの異なる値に変更しようとすると、さまざまな結果が得られました。
video/webm
-操作はサポートされていません
video/x-m4v
-MP4のように動作し、.stop()
が呼び出されたときにのみデータを取得しました
video/3gpp
-MP4のように動作
video/flv
-操作はサポートされていません
video/mpeg
-MP4のように動作
MP4のように動作するすべてのものから、実際に渡されているデータを検査するようになりましたhandleDataAvailable
。それは私がこれに気付いたときです:
どんなに何を私はビデオフォーマットのために選択し、Safariはいつも私にMP4を与えていました!
突然、サファリがこんなに悪夢だったのはなぜか、なぜそれを精神的に「とんでもないほど不可能」に分類したのかを思い出しました。複数のMP4をつなぎ合わせるには、JavaScriptトランスマルチプレクサーが必要です。
それは私が覚えていたときです、それはまさに以前にやったことです。MediaRecorderとSourceBufferを1年ほど前に使用して、JavaScript RTMPプレーヤーを作成してみました。プレーヤーが完成したら、MediaRecorderを使用してリングバッファーを1秒のビデオBLOBのメモリに保持することで、DVR(既にストリーミングされたビデオの一部に戻る)のサポートを追加したいと思いました。Safariでは、これらのビデオblobをMP4からISO-BMFFに変換するようにコード化したトランスマクサーを介して実行し、それらを連結できるようにしました。
コードをあなたと共有できればいいのですが、すべてコードは私の古い雇用主が所有しています。そのため、この時点では解決策はありません。誰かがemscriptenを使用してFFMPEGをJavaScriptにコンパイルする問題を経験したことを知っているので、あなたはそれを利用できるかもしれません。