Как проверить, поврежден ли файл, прежде чем объединять их с помощью FFmpeg?

#node.js #ffmpeg #child-process

#node.js #ffmpeg #дочерний процесс

Вопрос:

Я использую child_process пакет в NodeJS для запуска FFmpeg для объединения некоторых видео. Команда, которую я использую для объединения:

 ffmpeg -f concat -i list_file.txt -c copy final.mp4
 

это list_file.txt список видеофайлов, и он содержит:

 file '700010023590099933_1612945401707.mp4'
file '700010023590099933_1612945439023.mp4'
.
.
 

Я хочу проверить каждое видео, прежде чем объединять их, потому что, если одно из них повреждено, оно останавливает процесс и выдает ошибку. Таким образом, конечное видео также повреждается.

Кроме того, я могу проверить, в порядке ли видеофайл или нет, с помощью этой команды:

 ffmpeg -i input.mp4 -c copy -f null -; echo $?
 

это возвращает 0 , если файл в порядке, а 1 если нет.

Я хочу проверить все видеофайлы, и если все они в порядке, тогда объедините их. И если каждый из них был поврежден, исключите его и продолжите процесс. Есть ли способ сделать это одной командой?

Комментарии:

1. Итак, что вы делаете, если одно из видео повреждено? Исключить его из конкатенации? Вообще не выполнять конкатенацию? Если последнее, зачем вообще беспокоиться? Если конкатенация выдает ошибку, просто выбросьте результат.

2. Определенно, исключите это.

3. @derpirscher Спасибо. Я упоминал об этом в вопросе.

Ответ №1:

Вы можете прочитать текстовый файл, проанализировать его и создать для каждого видеофайла тестовый процесс.

 const fs = require("fs");
const cp = require("child_process");

const fileContent = fs.readFileSync("./videos.txt", "utf8").split("n").map((line) => {
    return line.match(/'([^'] )'/)[1];
});


const filterd = fileContent.filter((file) => {

    let corrupt = cp.execSync(`ffmpeg -i ./${file} -c copy -f null -; echo $?`, {
        stdio: "pipe",
        encoding: "utf8"
    }).trim();

    // corrupt = 0, file is ok, use it
    // corrupt = 1, file is corrupt, ignore it
    if (corrupt !== "0") {
        return false;
    } else {
        return true;
    }

});

// contains only fiels without error
console.log(filterd)
 

Сначала прочтите файл через fs.readFileSync и выполните некоторые манипуляции со строками, чтобы получить только те имена файлов, которые нам нужны / нужны.

Из проанализированного файла генерируется массив, по которому мы можем использовать filter. В filter creteria мы просто вызываем процесс тестирования ffmpeg и выполняем базовое сравнение строк, чтобы проверить, можно ли использовать файл или нет.

filterd Массив просто содержит имена файлов, которые могут быть обработаны. (Используйте полный, если вы хотите показать, какие файлы можно использовать, а какие нет)

Из этого массива теперь вы можете создать новый файл или передать его непосредственно в качестве аргумента file / input в ffmepg

 
var parseableFiles = "";

filterd.forEach((file) => {
    parseableFiles  = `file '${file}'rn`;
});

fs.writeFileSync("./filterd_files.txt", parseableFiles);
 

Обратите внимание, что я написал все вызовы функций syncron. Это блокирует цикл событий.
Также имейте в виду, что новая строка rn отличается от других операционных систем. -> https://en.wikipedia.org/wiki/Newline#Representation

Закодирован и протестирован на Ubuntu 18.04LTS.

Комментарии:

1. Да, я уже сделал это не совсем так, как вы сказали. Но я просто хотел узнать, есть ли лучший способ или нет. Большое вам спасибо.