ホーム > カテゴリ > PHP・Laravel >

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