Как проверить целостность видеофайла (avi, mpeg, mp4...)?
Это название может вводить в заблуждение, поэтому позвольте мне объяснить...
Я загружаю видеофайл... MPEG, AVI - будучи одним из популярных форматов. Теперь, если я загружаю его, а загрузка прерывается в середине загрузки... тогда, например, проигрыватель Windows Media выдаст какую-то ошибку и откажется воспроизводить ее (хотя файл, скажем, Заполнено на 98%). Но такие игроки, как KMPlayer или MediaPlayer Classic будут воспроизводить его до этого момента (фактически, они могут воспроизводить его и во время загрузки).
Итак, мне интересно... без использования каких-либо средств загрузки (менеджеров загрузки и т. П.) Для обеспечения полной загрузки файла, как можно проверить, был ли загружен видеофайл целиком и завершен ли он?
14 ответов
Вы можете использовать функцию в ffmpeg
видео конвертер: если вы укажете его, чтобы перекодировать видео в ноль, он просто прочитает входной файл и сообщит о появившихся ошибках. Это очень быстрый процесс, потому что видеокадры просто читаются, проверяются и незаметно сбрасываются.
Пример командной строки: (для Linux)
ffmpeg -v error -i file.avi -f null - 2>error.log
-v error
означает определенный уровень многословия (чтобы показать некоторые ошибки, которые обычно скрыты, потому что они не сильно влияют на играбельность).
Вы получите полный журнал ошибок с некоторой общей информацией о файле, который будет выводить ffmpeg, так что это, вероятно, потребует вашего внимания, через фильтры можно написать для выполнения пакетной проверки похожих файлов.
FFmpeg также доступен для Windows здесь. Командная строка будет практически идентична за исключением перенаправления stderr:
ffmpeg.exe -v error -i file.avi -f null - >error.log 2>&1
Мне понравилась идея использования ffmpeg -f null
выше, но я бы хотел автоматизировать процесс использования этого вывода. В частности, общий сценарий, который у меня есть с моей коллекцией музыкальных видео, состоит в том, что у меня есть несколько клипов с одинаковым разрешением, и я хотел бы просмотреть журналы проверки для этих файлов, чтобы удалить наиболее поврежденные.
К сожалению, пока у ffmpeg нет способа отключить интерактивный режим, который выводит шум для этого случая использования. В итоге я взломал простой скрипт-обертку для фильтрации:
#!/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
Пример вывода:
[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
Для окон вы можете "пакетно" проверить целостность видео в текущей папке и всех подпапках с помощью этого bat-файла:
checkvideo.bat
@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
Использование:
checkvideo.bat [filter]
Если вы не дадите один фильтр, получите "*.mp4".
Образцы: checkvideo.bat
checkvideo.bat *.avi
Установка: Загрузите FFmpeg для Windows отсюда: https://ffmpeg.zeranoe.com/builds/ и распакуйте их. Изменить C:\ffmpeg\bin\
в файле bat для пути куда вы распаковали ffmpeg Поставьте checkvideo.bat
в папке, включенной в путь, или добавьте его в переменную среды Path
Этот один лайнер проверяет каждый ввод и возвращает либоOK
илиERROR
, за которым следует имя файла.
for i in *; do ffprobe -v error "$i" 2>/dev/null && echo "OK => '$i'" || echo "ERROR => '$i'"; done
я создал фейк.mp4
файл, запустивtouch video.mp4
для имитации поврежденного видео. Результат:
OK => 'How To Be A Gardener 1x1 - Know Your Plot.mp4'
OK => 'How To Be A Gardener 1x2 - Understand Plants.mp4'
OK => 'How To Be A Gardener 1x3 - Planting Schemes & Themes.mp4'
OK => 'How To Be A Gardener 1x4 - Practical Planting.mp4'
OK => 'How To Be A Gardener 1x5 - Caring For Your Garden.mp4'
OK => 'How To Be A Gardener 1x6 - Problem Solving.mp4'
OK => 'How To Be A Gardener 1x7 - The Productive Garden.mp4'
OK => 'How To Be A Gardener 1x8 - The Gardening Year.mp4'
ERROR => 'video.mp4'
Настоящийffprobe
ошибки можно увидеть, удалив2>/dev/null
перенаправление:
for i in *; do ffprobe -v error "$i" && echo "OK => '$i'" || echo "ERROR => '$i'"; done
OK => 'How To Be A Gardener 1x1 - Know Your Plot.mp4'
OK => 'How To Be A Gardener 1x2 - Understand Plants.mp4'
OK => 'How To Be A Gardener 1x3 - Planting Schemes & Themes.mp4'
OK => 'How To Be A Gardener 1x4 - Practical Planting.mp4'
OK => 'How To Be A Gardener 1x5 - Caring For Your Garden.mp4'
OK => 'How To Be A Gardener 1x6 - Problem Solving.mp4'
OK => 'How To Be A Gardener 1x7 - The Productive Garden.mp4'
OK => 'How To Be A Gardener 1x8 - The Gardening Year.mp4'
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x559de0c58900] moov atom not found
video.mp4: Invalid data found when processing input
ERROR => 'video.mp4'
Настроитьfor
цикл для проверки только определенных расширений или файлов:
for i in *.mkv; do ...
for i in *S01E*.mp4; do ...
Проблема с другим ответом с помощью ffmpeg
перекодировать в null
Формат в том, что это занимает действительно много времени. Особенно, если вы хотите проверить несколько файлов в каталоге.
Быстрый способ - создать миниатюры для всех видео и посмотреть, где не удается создать миниатюру.
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;
Этот метод оказался намного быстрее, чем другие методы.
Тем не менее, есть CAVEAT. Этот метод может дать неправильные результаты, потому что иногда миниатюра может быть сгенерирована даже для поврежденных файлов. Например, если видеофайл поврежден только в конце, этот метод не удастся.
Мне очень понравилась версия ffmpeg, предоставленная Как проверить целостность видеофайла (avi, mpeg, mp4...)?но мне нужна была версия, которая сообщала бы мне только о том, что ffmpeg не смог воспроизвести видео таким образом, чтобы остановить его (я могу справиться с пропаданием кадров), и я хотел, чтобы она была основана на Linux. Я пришел к решению ниже. Мне также хотелось получить больше информации о том, что происходит во время сканирования, поэтому я выбрал вывод отсканированных/итого/ошибочных файлов при каждом запуске сканирования.
#!/bin/bash
# Name: mediaCheck
# Purpose: Confirm all media in a path can be played back using ffmpeg
# Requires:
# * ffmpeg in $PATH
# * date in $PATH
# * find in $PATH
function checkReqs {
# checks requirements for the script
requires="ffmpeg date find"
re=0
for i in $requires; do
if ! which $i > /dev/null; then
((re++))
echo "$i is required in path for this script"
fi
done
if [ "$re" -gt 0 ]; then
echo "Requirements not met"
exit 1
fi
}
function pathCheck {
# if there isn't a path, use pwd, otherwise clean up whatever is provided.
if [ -z "$1" ]; then
lPath=mediaCheck.log
cPath=$(pwd)
else
cPath=$(readlink -f $1)
lPath=$1
fi
}
function pdate {
# my prefered date formatting
date +%FT%H:%M:%S
}
function checkMedia {
# the actual ffmpeg command
ffmpeg -v error -i $1 -f null - &> "$1.log"
}
function findItems {
# our main loops
# first a set of common file types
for mtype in flv avi m4v mkv mp4; do
c=0; e=0
# Get a total per file type
ttotal=$(find $1 -type f -name \*.$mtype | wc -l)
# then the actual lookup and check
for i in $(find $1 -type f -name \*.$mtype); do
echo -ne "$(pdate) $c out of $ttotal $mtype files checked with $e errors.\r"
((c++))
# check media, and if we fail, increment error counter.
if ! checkMedia "$i" ; then
((e++))
echo "$i failed" >> $lPath.log
fi
done
echo "$(pdate) $c out of $ttotal $mtype files checked with $e errors."
unset c e
done
}
# set blank cpath
cPath=''
# uncomment the line below if this script isn't behaving as expected
# set -x
# Check requirements before anything else
checkReqs
# Then generate a path
pathCheck $1
# Make sure we don't stumble on names with spaces
IFS=$'\n'
echo "$(pdate) scan started."
findItems $cPath
echo "$(pdate) scan complete."
Хотя это старый пост, и я уверен, что сейчас есть другие способы проверки видеофайлов. Однако для полной проверки видеофайла вы можете использовать mplayer.exe.
Использование приведенного ниже сценария (.bat) будет рекурсивно проверять видеофайлы и сохранять проверенные в файле целостности.log (чтобы пропустить его при следующем запуске).
if not "%1" equ "" (
pushd %1
) else (
pushd "%~dp0"
)
setlocal EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
set "DEL=%%a"
)
echo This script with validate video files in the folder/sub-folders. Please ensure mplayer.exe is accessible in PATH.
echo.
echo Either run this script from the desired (parent) directory or specify the directory when running this script. eg checkvideo.bat <full path>
echo.
pause
echo.
REM Append date and time to integritychecked.log file
for /f "tokens=1-9 delims=/:. " %%d in ("%date% %time: =0%") do echo Started: %%g%%f%%e_%%h%%i%%j>>integritychecked.log
FOR /F "delims=*" %%G in ('dir /b /s *.mkv *.mp4 *.mpg *.mpeg *.xvid *.webm *.m2v *.m4v *.3gp *.3g2 *.avi *.mov *.flv *.wmv') DO (
REM Confirm if already checked or not from log file
set found=0
for /F "usebackq tokens=*" %%s in ("integritychecked.log") do (
if %%G equ %%s (
set found=1
REM echo "FOUND = %%G = %%s"
)
)
if !found! equ 0 (
echo Verifying "%%G"
mplayer -tsprobe 10000000 -benchmark -forcedsubsonly -mc 0 -nosound -nosub -noautosub -vo null "%%G" 2>"%%G.log"
REM ffmpeg -v error -i "%%G" -map 0:1 -f null - 2>"%%G.log"
FOR %%F in ("%%G.log") DO (
if %%~zF equ 0 (
del %%F
call :colour 0a "Video is good"
echo.
echo.
) else (
call :colour 0c "Error in video file:"
echo.
type %%F
call :colour 0e "This can be found in the video's .log file"
echo.
echo.
)
)
REM Save entry to log file (as checked)
echo %%G>>integritychecked.log
) else (
echo already verified "%%G"...skipping.
)
)
call :colour 0a "Verifying complete!" && echo.
pause
cd %~p0
exit /b
:colour
set "param=^%~2" !
set "param=!param:"=\"!"
rem Prepare a file "X" with only one dot
<nul > X set /p ".=."
findstr /p /A:%1 "." "!param!\..\X" nul
<nul set /p ".=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
rem Delete "X" file
del X
exit /b
Я разработал этот скрипт Python, который проверяет целостность медиафайлов (или пытается это сделать). Пожалуйста, прочитайте инструкции для получения подробной информации и ограничений, также приветствуются отзывы:https://github.com/ftarlao/check-media-integrity
Более простая версия
for file in *.mp4; do ffmpeg -v error -i "$file" -f null - >error.log 2>&1; print "$file"; done
Это напечатает имя файла, поскольку они обрабатываются.
error.log
будет содержать ошибки.
def check(dirpath):
files = [f for f in listdir(dirpath) if isfile(join(dirpath, f))]
invalidfiles = []
for filename in files:
cmd_args = ['ffprobe', dirpath + '/' + filename]
pipes = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
#If you are using python 2.x, you need to include shell=True in the above line
std_out, std_err = pipes.communicate()
if 'invalid data' in std_out.decode('utf-8').lower() :
invalidfiles.append(dirpath + '/' + filename)
continue
if 'invalid data' in std_err.decode('utf-8').lower() :
invalidfiles.append(dirpath + '/' + filename)
continue
return invalidfiles
Я написал обертку дляffmpeg
команда в виде программы Python с графическим интерфейсом для пакетного сканирования видеофайлов в выбранном каталоге; оценка того, являются ли файлы здоровыми или поврежденными. Это основано на команде, опубликованной выше:ffmpeg -v error -i file.avi -f null - 2>error.log
Программа поддерживается в Windows и macOS и представляет собой переносимый исполняемый файл для любой ОС. Просто скачайте и запустите. С уважением!
Я использую однострочник:
nice find . \( -iname \*.mp4 -o -iname \*.avi -o -iname \*.mkv \) -exec bash -c 'ffmpeg -v error -xerror -i "{}" -f null - || echo error in "{}"' \;
-
nice
снижает приоритет, чтобы не мешать работе системы -
find
ищет файлы MP4/AVI/MKV (без учета регистра) рекурсивно, начиная с текущего каталога -
ffmpeg -xerror
останавливается с кодом ошибки при первой ошибке декодирования -
echo
печатает имя поврежденного файла
По моему опыту, добавление-map 0:1
возможностьffmpeg
(чтобы декодировать только аудио) может значительно ускорить обработку, но ценой ложноотрицательных результатов. Например, он редко обнаруживает неполные файлы MP4, поскольку аудиоданные обычно занимают около 10% от общего объема клипа, поэтому вероятность того, что произвольное вырезание файла повредит звуковую дорожку, также составляет около 10%.
свободный-ffmpeg
var ffmpeg = require('fluent-ffmpeg');
var ff = new ffmpeg();
ff.on('start', function(commandLine) {
// on start, you can verify the command line to be used
})
.on('progress', function(data) {
// do something with progress data if you like
})
.on('end', function() {
// do something when complete
})
.on('error', function(err, stdout, stderr) {
// handle error conditions
console.log('Error: ' + err.message)
console.log('ffmpeg output:\n' + stdout)
console.log('ffmpeg stderr:\n' + stderr)
})
.addInput('path\to\file')
.addInputOption('-xerror')
.addInputOption('-v error')
.output('-')
.outputOptions('-f null')
.run();
Справка:
MediaInfo - это отличный инструмент для получения информации о любом видеофайле, который вы хотите добавить. Это может быть в состоянии выделить информацию, которую вы хотите.
Другим инструментом является GSpot, но он не обновлялся с 2007 года.
Попробуйте дать каждому известный хороший и известный плохой файл и сравните результаты.
Я использовал GSpot до тех пор, пока он не перестал обновляться, затем переключился на MediaInfo