l3tnun / EPGStation

Mirakurun を使用した録画管理ソフト
https://twitter.com/l3tnun
MIT License
553 stars 149 forks source link

エンコードに失敗する場合がある #583

Closed ohkini closed 2 years ago

ohkini commented 2 years ago

環境

docker-mirakurun-epgstation + chinachu/mirakurunにて構築しています

Issue

このような便利なソフトを提供くださり感謝しております。

自動/手動を問わずエンコードに失敗する場合があります。失敗する場合、大抵のケースでは0KBのmp4ファイルが作成されますが、数百KBで終わることもまれにあります。 失敗した場合、すべてのケースにおいてエンコードタブにキューが表示され0KBの場合一瞬で消えます。 エンコードに失敗したTSファイルを再度WebUIから手動でエンコードした場合、成功する/途中で止まる/失敗するケースに分かれますが、失敗しかしないファイルもあります。 失敗しかしないTSファイルでも、VLC for Windowsでは正しく再生できます。また、tsselectなどで調べてもドロップ/エラー/スクランブル未解除などはありません。

Issue #516 を参考にDockerfile内を     ENV FFMPEG_VERSION=4.1.6     --enable-libaribb24 ←削除 に変更し enc.js の中身をenc.js.templateから丸ごとコピペした後に再度ビルド(docker-compose build --force-rm --no-cache)し直しましたが、上記現象は解消されません。

以下に失敗時のログの抜粋を添付いたします。

Service/encode.log

[mpegts @ 0x55ead878c400] Could not find codec parameters for stream 10 (Unknown: none ([13][0][0][0] / 0x000D)): unknown codec Consider increasing the value for the 'analyzeduration' and 'probesize' options [mpegts @ 0x55ead878c400] Could not find codec parameters for stream 15 (Audio: aac ([15][0][0][0] / 0x000F), 0 channels): unspecified sample format Consider increasing the value for the 'analyzeduration' and 'probesize' options

[2022-02-17T19:35:46.366] [DEBUG] encode - Too many packets buffered for output stream 0:1.

[2022-02-17T19:35:46.367] [DEBUG] encode - [aac @ 0x55ead8805940] Qavg: 202.677

[aac @ 0x55ead8805940] 2 frames left in the queue on closing

[2022-02-17T19:35:46.367] [DEBUG] encode - Conversion failed!

Operator/system.log

[2022-02-17T19:35:46.377] [INFO] system - add video file: 487 2022年02月17日15時00分00秒-将棋フォーカス「好対照!新四段 横山友紀&狩山幹生」.mp4 [2022-02-17T19:35:46.393] [INFO] system - encodingFinishCommand: undefined

お忙しい中大変恐縮ですが、他のチェック箇所や修正個所などご教示いただけましたら幸いです。

5ym commented 2 years ago

エンコードするファイルに存在しないストリームが含まれているからだと思われます 例えば前番組が字幕ありで次番組が字幕なしの場合ファイルの先頭に字幕ストリームがあるとの情報が含まれてしまうためエンコードに失敗する場合がありますその場合-mapオプションを用いて特定のストリームを除外するかファイルの先頭を削除すればエンコードできるようになります

ohkini commented 2 years ago

sym様 ありがとうございます。改めて録画に失敗した番組を見てみると、ほとんどが前番組とストリーム数が違うものだったと思います。 録画開始マージンを調整するか、エンコード前にファイル先頭削除のスクリプトを挟む対処を試してみようと思います。重ね重ねありがとうございました。

5ym commented 2 years ago

参考までに自分が録画している番組では音声ストリームが前番組と被りやすいので以下のようにしていますこれだけで大体の番組はエラーでずにエンコードできています

Array.prototype.push.apply(args, ['-map', '0:a', '-map', '-0:13?', '-map', '-0:10?']);
i12o commented 2 years ago

私の所でも enc.js を使ってエンコードしようとした後、ffmpeg がきちんと変換できていないファイルを出力しながら、終了ステータス 0 で終了する事がたまに起こります。「元ファイルを自動削除」オプションと合わせて使っているととても悲しい事になってしまいます。 原因としていろいろあるにせよ、ちょっと不便なので、ffmpeg が 0 で終了したとしても、outputファイルをチェックしてある程度のサイズより小さい場合、異常終了と見做させるなどの対応を入れる事はできませんでしょうか。 様々なユースケースがあるとは思いますが、ビデオストリームで10Kバイトより小さいアウトプットしかない場合は何かしらおかしい、というような判断であればさほど問題ないと思うのですが、いかがでしょうか。

ohkini commented 2 years ago

sym様 ありがとうございます。ご教示頂いた内容を参考にenc.jsを修正しテストしてみます。 まだまだ不勉強のため、結果のご報告などすぐにはできないかもしれませんが、ご容赦いただければと思います。

あとマージンの調整は、マージンを0にした上で40番組ほど録画してみましたが、少し改善したかなとは思うものの、あまり芳しい結果は得られませんでした。蛇足ながら参考として記載します。

問題点を指摘いただいたうえで再度Issueを見直してみると#244,#247あたりにヒントがあるような気がしてきました。こちらに記載の事項についても試してみようと思います。

ohkini commented 2 years ago

色々試した結果、現状下記組み合わせのみエンコードの際エラーが出ませんでした。

epgstation/config/enc.js

// オーディオストリーム設定 Array.prototype.push.apply(args, ['-map', '0:a', '-map', '-0:13?', '-map', '-0:10?']); Array.prototype.push.apply(args, ['-c:a', 'aac']); // 字幕ストリーム設定(削除) //Array.prototype.push.apply(args, ['-map', '0:s?', '-c:s', 'mov_text']);

上記のうち、オーディオストリーム設定のみ変更、字幕ストリーム設定のみ削除はまれにエンコードエラーが出ました。 また、前番組がサブで本番組がメインチャンネルのような場合は上記設定でもエンコード不可でした。 ほぼ全てのストリームを保ったままエンコードしようとすると、おそらく外部ソフトに頼るかコードにかなり手を加える必要があるかと思いますので、i12o様がご提案されたように、エンコード後のファイルサイズによっては元ファイルを削除しないオプションがあるとうれしいかなと私も思います。

ちなみに、0バイトでエンコードが終了する原因としては、種類の違うストリームに書き込もうとして書き込めずffmpegがこけるのではないかなという印象です。見当違いでしたらすみません。

i12o commented 2 years ago

node.js のやり方はよく理解していないんですが、 config/enc.js に

先頭の方でこれ宣言に入れといて

const fs = require('fs');

後ろの方にこんなブロック追加して、10kより小さかったらエラーを発生させるようにできた、ような気がします。

child.on('exit', (code) => {
    console.error("Exited with code: " + String(code));
    console.error("Output: " + String(output));
    var stat = fs.statSync(output);
    console.error(stat.size);
    if (stat.size < 10 * 1024) {
        console.error("File site too small (< 10k). Raising error");
        throw new Error(1);
    }
});

簡単に実験した範囲では、フェイルセーフとして働いてくれてる気がしてます。

すみません、あまりコードとしてこれで良いという自身がなくて、単なる動作確認のために入れてる log 行とか含まれてます。

ohkini commented 2 years ago

i12o様 ありがとうございます。お返事遅くなり申し訳ありません。 こちらでも検証した結果、問題なく動作しております。最終的に現在のところ、enc.jsにi12o様のブロックを組み込み、enc2.jsを作成しオーディオストリームと字幕ストリームの設定を変更したうえでブロック組み込みしました。 録画時はenc.jsをエンコードに指定し、失敗したものはenc2.jsで再度エンコードしております。これでほぼほぼエンコードが完了でき、またまれにあるエンコード不可時も元ファイルが残っており、安心してエンコード時に元ファイル削除のオプションを付加できております。 5ym様、i12o様に助けていただき録画ファイルの喪失回避ができました。重ねてお礼申し上げます。

FJ5525 commented 1 year ago

私も同じような症状で困っていた所上記の設定で解決できました。 ありがとうございます。