Audioタグでシーク(再生位置を調整)が機能しない[Audio seeking not working]
FireFoxでは動作するのにChrome/EdgeだとAudioタグで読み込んだ音声ファイル(MP3/OGGなど)の「再生位置の調整」(シーク)が機能しない場合があります。今回はその対処方法です。
発生した環境
・Laravel (PHP)で発生。 |
Stack OverflowのAudio seeking not workingでも問題となっていましたが、未解決でした。結論から先にいうとLaravelとPHPのバグではないです。PythonやJavaなどの他のWeb系開発環境でも発生する可能性が高いです。
問題のコード (Laravel)
[ビュー]
<audio controls src="download?f=20201123.mp3" ></audio>
[コントローラー]
$file = base_path() . "/save/" . $request->f; header('Content-Type: audio/mpeg'); header('Content-Length: ' . filesize($file)); header('Content-Disposition: attachment; filename="' . $request->f . '"'); readfile($file);
調査
シークは出来たりできなかったするケースがありましたので、両方のHTTPヘッダをcurlコマンドで調査しました。
curl --verbose http://www.???.com/ok.mp3 1> /dev/null curl --verbose http://www.???.com/no.mp3 1> /dev/null
ダメな場合
< HTTP/1.1 200 OK < Host: localhost:8000 < Date: Tue, 24 Nov 2020 11:10:33 GMT < Connection: close < X-Powered-By: PHP/7.4.10 < Content-Type: audio/mpeg < Content-Length: 1087872 < Content-Disposition: attachment; filename="test.mp3"
OKの場合
< HTTP/1.1 200 OK < Server: nginx < Date: Tue, 24 Nov 2020 11:10:33 GMT < Content-Type: audio/mpeg < Content-Length: 1087872 < Accept-Ranges: bytes
結論 (Conclusion)
見て頂くとわかると思いますが、
Accept-Ranges: bytes |
です。これをHTTPのヘッダに付与すればaudioタグで再生位置をシークする事ができました。以下は、修正後のファイルです。
$file = base_path() . "/save/" . $request->f; header('Content-Type: audio/mpeg'); header('Content-Length: ' . filesize($file)); header('Content-Disposition: attachment; filename="' . $request->f . '"'); // これがないとChrome/Egdeではaudioタグでシークできない header('Accept-Ranges: bytes'); readfile($file);
以上となります。
参考文献
Accept-Ranges (MDN)
スポンサーリンク
関連記事
公開日:2020年11月24日
記事NO:02862