как проверить целостность видеофайла (avi, mpeg, mp4 ...)?

<p>это название может вводить в заблуждение, поэтому позвольте мне объяснить ...</p><p>я загружаю видеофайл ... mpeg, avi - будучи одним из популярных форматов. теперь, если я загружаю его, а загрузка прерывается в середине загрузки ... тогда, например, проигрыватель windows media выдаст какую-то ошибку и откажется воспроизводить ее (хотя файл, скажем, заполнено на 98%). но такие игроки, как kmplayer или mediaplayer classic будут воспроизводить его до этого момента (фактически, они могут воспроизводить его и во время загрузки).</p><p>итак, мне интересно ... без использования каких-либо средств загрузки (менеджеров загрузки и т. п.) для обеспечения полной загрузки файла, как можно проверить, был ли загружен видеофайл целиком и завершен ли он?</p>

<p>вы можете использовать функцию в видео конвертере <code>ffmpeg</code>: если вы укажете ее, чтобы перекодировать видео в ноль, он просто прочитает входной файл и сообщит обо всех появившихся ошибках. это очень быстрый процесс, потому что видеокадры просто читаются, проверяются и незаметно сбрасываются.</p><p>пример командной строки: (для linux)</p><pre><code>ffmpeg -v error -i file.avi -f null - 2>error.log </code></pre><p><code>-v error</code> означает определенный <a href="http://ffmpeg.org/ffmpeg.html">уровень детализации</a> (чтобы показать некоторые ошибки, которые обычно скрыты, поскольку они не сильно влияют на играбельность).</p><p>вы получите полный журнал ошибок с некоторой общей информацией о файле, который будет выводить ffmpeg, так что это, вероятно, потребует вашего внимания, через фильтры можно написать для выполнения пакетной проверки похожих файлов.</p><p>ffmpeg также доступен для windows <a href="http://ffmpeg.zeranoe.com/builds/">здесь</a> . командная строка будет практически идентична за исключением перенаправления stderr:</p><pre><code>ffmpeg.exe -v error -i file.avi -f null - >error.log 2>&1 </code></pre>

<p>мне понравилась идея использования <code>ffmpeg -f null</code> выше, но я бы хотел автоматизировать процесс использования этого вывода. в частности, общий сценарий, который у меня есть с моей коллекцией музыкальных видео, состоит в том, что у меня есть несколько клипов с одинаковым разрешением, и я хотел бы просмотреть журналы проверки для этих файлов, чтобы удалить поврежденные.</p><p>к сожалению, пока у ffmpeg нет способа отключить интерактивный режим, который выводит шум для этого случая использования. в итоге я взломал простой скрипт-обертку для фильтрации:</p><pre><code>#!/usr/bin/env python import sys import os import re t = os.popen('ffmpeg -v 5 -i "%s" -f null - 2>&1' % sys.argv[1]).read() t = re.sub(r"frame=.+?\r", "", t) t = re.sub(r"\[(.+?) @ 0x.+?\]", "[\\1]", t) print t </code></pre><p>пример вывода:</p><pre><code>[mpeg1video]ac-tex damaged at 21 17 [mpeg1video]warning mvs not available [mpeg1video]concealing 22 dc, 22 ac, 22 mv errors [mpeg1video]warning mvs not available [mpeg1video]concealing 22 dc, 22 ac, 22 mv errors [mpeg1video]ac-tex damaged at 13 9 </code></pre>

<p>проблема с другим ответом, использующим <code>ffmpeg</code> для перекодирования в формат <code>null</code>, заключается в том, что это действительно занимает много времени. особенно, если вы хотите проверить несколько файлов в каталоге.</p><p>быстрый способ - создать миниатюры для всех видео и посмотреть, где не удается создать миниатюру.</p><pre class="lang-sh prettyprint-override"><code>find . -iname "*.mp4" | while read -r line; do line=`echo "$line" | sed -r 's/^w+//g'; echo 'here it is ==>' "$line"; if ffmpeg -i "$line" -t 2 -r 0.5 %d.jpg; then echo "done for" "$line"; else echo "failed for" "$line" >>error.log; fi; done; </code></pre><p>этот метод оказался намного быстрее, чем другие методы.</p><p>тем не менее, есть caveat. этот метод может дать неправильные результаты, потому что иногда миниатюра может быть сгенерирована даже для поврежденных файлов. например. если видеофайл поврежден только в конце, этот метод завершится ошибкой.</p>

<p>для окон вы можете «пакетно» проверить целостность видео в текущей папке и всех подпапках с помощью этого bat-файла:</p><p><code>checkvideo.bat</code></p><pre><code>@echo off set "filtro=%1" if [%filtro%]==[] ( set "filtro=*.mp4" ) for /r %%a in (%filtro%) do call :dowork "%%a" pause exit /b :dowork c:\ffmpeg\bin\ffmpeg.exe -v error -i %1 -f null - > "%~1.log" 2>&1 </code></pre><p><strong> использовать: </strong></p><p><code>checkvideo.bat [filter]</code></p><p>если вы не дадите один фильтр, получите «* .mp4».</p><p>образцы: <code>checkvideo.bat</code> <code>checkvideo.bat *.avi</code></p><p><strong> настройка: </strong>загрузите ffmpeg для windows отсюда: <a href="https://ffmpeg.zeranoe.com/builds/">https://ffmpeg.zeranoe.com/builds/</a> и разархивируйте их. измените <code>c:\ffmpeg\bin\</code> в файле bat для пути, по которому вы распаковали ffmpeg. поставьте <code>checkvideo.bat</code> в папке, включенной в путь, или добавьте его в переменную среды path</p>

<p> <a href="http://mediainfo.sourceforge.net/">mediainfo</a> это отличный инструмент для получения информации о любом видеофайле, который вы хотите добавить. это может быть в состоянии выделить информацию, которую вы хотите.</p><p>другим инструментом является <a href="http://www.headbands.com/gspot/">gspot</a> , но он не обновлялся с 2007 года.</p><p>попробуйте дать каждому известный хороший и известный плохой файл и сравните результаты.</p><p>я использовал gspot до тех пор, пока он не перестал обновляться, затем переключился на mediainfo</p>