前提・実現したいこと
勉強がてらmpeg-dashのプレイヤーを自作しています
発生している問題・エラーメッセージ
chromeでのみ、2度目のfetchが完了しません。
chrome(v94.0.4606.81) on windows10
chrome(v92.0.4515.159) on macos bigsur(v11.6)
firefox(v93.0) on windows10
firefox(v93.0) on macos bigsur(v11.6)
safari(v15.0) on macos bigsur(v11.6)
※1回目のfetchで取得した分に関しては再生できてます。
該当のソースコード
クライアント側
html
1<video id="video" controls="" style="width: 100%; height: 100%;"></video> 2<meta charset="utf-8"> 3 4<script type="text/javascript"> 5var FILE = "";//request url 6var chunk_size = 10 * 1024 * 1024; // 10mb 7var current_chunk = 1; 8var file_size = chunk_size+1; 9 10window.MediaSource = window.MediaSource || window.WebKitMediaSource; 11if (!!!window.MediaSource) { 12 alert('MediaSource API is not available'); 13} 14 15var mediaSource = new MediaSource(); 16var sourceBuffer; 17let is_buffering = false; 18 19let readChunkfunc; 20 21video.src = window.URL.createObjectURL(mediaSource); 22 23async function callback(e) { 24 sourceBuffer = mediaSource.addSourceBuffer('video/mp4;codecs="avc1.4D401F,mp4a.40.2"'); 25 26 console.log('mediaSource readyState: ' + this.readyState); 27 28 var readChunk = async(chunk)=> { 29 const req = await fetch(FILE,{headers:{'Range':'bytes='+(chunk*chunk_size)+'-'+(((chunk+1)*chunk_size<=file_size)?((chunk+1)*chunk_size-1):(file_size-1))}}); 30 const res = await req.arrayBuffer(); 31 for(let value of req.headers.entries()){ 32 if (value[0]=='content-range') { 33 file_size = parseInt(value[1].split("/").pop()); 34 } 35 } 36 sourceBuffer.appendBuffer(new Uint8Array(res)); 37 }; 38 39 sourceBuffer.addEventListener('update', async function(e) { 40 if (!sourceBuffer.updating) { 41 console.log(current_chunk , Math.ceil(file_size/chunk_size)); 42 if (current_chunk > Math.ceil(file_size/chunk_size)-1) { 43 if ( mediaSource.readyState!='ended' ){ 44 mediaSource.endOfStream(); 45 } 46 return; 47 } 48 if (is_buffering) { 49 return; 50 } 51 is_buffering=true; 52 if (video.buffered.end(0)-60<video.currentTime&¤t_chunk < Math.ceil(file_size/chunk_size)) { 53 await readChunk(current_chunk); 54 current_chunk++; 55 } 56 is_buffering=false; 57 } 58 }); 59 is_buffering=true; 60 await readChunk(0); 61 is_buffering=false; 62 const updateBuffer=async(istimeout)=>{ 63 if (is_buffering&&istimeout!==true) { 64 return; 65 } 66 is_buffering=true; 67 if (video.buffered.end(0)-60<video.currentTime&¤t_chunk < Math.ceil(file_size/chunk_size)) { 68 await readChunk(current_chunk);//おそらくここのfetchで止まってる 69 current_chunk++; 70 } 71 is_buffering=false; 72 } 73 video.ontimeupdate=updateBuffer; 74 video.onplay=updateBuffer; 75 video.onpause=updateBuffer; 76 readChunkfunc=updateBuffer; 77} 78 79mediaSource.addEventListener('sourceopen', callback, false); 80mediaSource.addEventListener('webkitsourceopen', callback, false); 81 82mediaSource.addEventListener('webkitsourceended', function(e) { 83 console.log('mediaSource readyState: ' + this.readyState); 84}, false); 85</script>
サーバー側
php
1<?php 2/* 3 4認証処理とかパスの生成(略) 5 6ダウンロード処理(ResumeDownload):https://gist.github.com/kosinix/4cf0d432638817888149 7 8*/ 9$request_text="/mnt/f".urldecode(implode("/", $request)); 10if (substr($request_text, -1)=="/") { 11 $request_text=substr($request_text, 0, -1); 12} 13if (!@file_exists($request_text)) { 14 header( "HTTP/1.1 404 Not Found" ); 15 exit; 16} 17if (@is_dir($request_text)) { 18 header( "HTTP/1.1 404 Not Found" ); 19 exit; 20} 21set_time_limit(0); 22$download = new ResumeDownload($request_text); //delay about in microsecs 23$download->process(); 24 25
試したこと
何種類か動画を差し替えて試したところ、2回目のfetchの容量が10mbに満たない場合は読み込みに成功しました
また、2回目のfetch分を別ファイルとしてphpを介さずapacheから取得してみましたが、同様にfetchが完了しませんでした。
おそらくchromeの独自仕様のせいだと思うんですが如何せん情報がないもので。
なにかわかる方いらっしゃいましたらよろしくおねがいします。
補足情報(FW/ツールのバージョンなど)
・サーバー
OS: Ubuntu 20.04.3 LTS on Windows 10 x86_64
Kernel: 4.4.0-19041-Microsoft
Apache/2.4.41 (Ubuntu)
PHP 8.0.11 (cli) (built: Sep 23 2021 21:26:24) ( NTS )
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。