バックグラウンド
基本的にクライアント側でビデオを生成できる内部プロジェクトに取り組んでいますが、認識している JavaScript ビデオ エンコーダーがないため、各フレームを個別にエクスポートしています。サーバーへのアップロードを避ける必要があります。これはすべてクライアント側で行われます。
実装
このFileSaver.js (より具体的には、Chrome の webkit FileSystem API) を使用して、HTML5 キャンバスによって生成された多数の PNG を保存しています。特定のフォルダーに自動的にダウンロードするように Chrome を設定したので、[保存] をクリックすると、1 秒あたり 20 枚の画像が保存されます。これは私の目的のために完全に機能します。
JSZipを使用してこれらすべてのフレームを 1 つのファイルに圧縮してから、クライアントに保存してもらうことができれば、そうすることができますが、ブラウザーが ~8000 個の 640x480 PNG を生成するのに十分なメモリを確保する方法がないため、試したこともありません。次にそれらを圧縮します。
問題
問題は、一定数の画像の後、ダウンロードされたすべてのファイルが空になることです。Chrome は、ダウンロード バーで、ファイルが 0 バイトであることを通知し始めます。同じエクスポート設定で同じプロジェクトで繰り返されると、空の保存がまったく同時に開始されます。たとえば、あるプロジェクトでは、チョークする前に最初の 5494 フレームを保存できます。(これがとてつもなく大きな数であることはわかっていますが、どうしようもありません。) 保存の間に 10 ミリ秒の遅延を設定しようとしましたが、効果はありませんでした。このままではエクスポートに非常に時間がかかるため、それ以上の遅延は試していません。
blob.size を確認しましたが、決してゼロではありません。クォータを超えていると思われますが、エラーはスローされません。サンドボックスへの書き込み、またはユーザーが指定した場所へのファイルのコピーに失敗するだけです。
質問
これらの空の保存を検出するにはどうすればよいですか? それらを防ぎますか?これを行うより良い方法はありますか?私はただめちゃくちゃですか?
編集:実際、FileSaver.js をデバッグした後、webkitRequestFileSystem を使用していないことに気付きました。ここに来ると戻ります:
if (can_use_save_link) {
object_url = get_object_url(blob);
save_link.href = object_url;
save_link.download = name;
if (click(save_link)) {
filesaver.readyState = filesaver.DONE;
dispatch_all();
return;
}
}
そのため、FileSystem API を使用していないように見えるため、ストレージがいっぱいになる前にストレージを空にする方法がわかりません。
編集 2:「if (can_use_save_link)」ブロックを「writer.onwriteend」関数内に移動して、次のように変更してみました:
if (can_use_save_link) {
save_link.href = file.toURL();
save_link.download = name;
click(save_link);
}else{
target_view.location.href = file.toURL();
}
その結果、クォータ付きのストレージを使用しているため、8260 個のファイル (合計約 1.5 GB) をすべて保存できます。以前は、アンカー要素が 'download' 属性をサポートしている場合、ファイルを配置する必要がなかったので、ファイルは HTML5 FileSystem に表示されませんでした。
また、ファイル名に「.download」を追加するコードをコメント アウトすることもできました。また、「file.remove()」の両方のインスタンスに引数として空の無名関数を指定する必要がありました。