Problemas para automatizar la concatinación (fusión) de archivos VOB de DVD con FFMPEG

Problemas para automatizar la concatinación (fusión) de archivos VOB de DVD con FFMPEG

Tengo una biblioteca de DVD descifrados, todos los cuales tienen su video en una serie de archivos VOB dentro de la carpeta VIDEO_TS habitual. Me preguntaba si podría usar FFMPEG para combinarlos en un solo archivo MPEG. Primero encontré esto (el ejemplo supone 2 archivos VOB) de una publicación antigua que no es de intercambio de pila, y funciona...

ffmpeg -i "concat:VTS_01_1.VOB|VTS_01_2.VOB" -f DVD -c copy output.mpg

ffmpeg a veces se queja de posibles marcas de tiempo faltantes, pero no he visto ningún problema en el video, el audio o la sincronización. Esto también funciona con quejas ligeramente diferentes.

ffmpeg -i "concat:VTS_01_1.VOB|VTS_01_2.VOB" -f mpeg -c copy output.mpeg

Así que escribí un archivo por lotes (Windows 10) que reúne la cantidad de archivos VOB que quiero procesar. Lo que esperaba hacer entonces es crear la cadena "concat" para que FFMPEG la procese. Pero lo hice a mano solo para intentarlo así...

set concat="concat: VTS_01_1.VOB|VTS_01_2.VOB|VTS_01_3.VOB|VTS_01_4.VOB|VTS_01_5.VOB"

Luego intenté pasar esa cadena a FFMPEG así en mi archivo por lotes

ffmpeg -i %concat% -f DVD -c copiar salida.mpg

Bueno, eso no funciona en absoluto. Supongo que FFMPEG no puede reconocer la variable de cadena como sustituto. Así que busqué los documentos de ffmpeg sobre el tema "concat" y sugieren usar una lista de archivos almacenados en un archivo de texto, como este...

file 'VTS_01_1.VOB'
file 'VTS_01_2.VOB' (etc...)

Luego, guardar el archivo como "mylist.txt" y usar una llamada a FFMPEG como esta...

ffmpeg -f concat -safe 0 -i milista.txt -c copiar salida.mpg

Bueno, lo intenté y no funcionó muy bien. Después del primer archivo VOB, recibía continuas advertencias sobre el desbordamiento del búfer y las marcas de tiempo, y el proceso de concatenación, generalmente rápido, se ralentizó hasta el punto de ralentizarse. Las advertencias normalmente tenían este aspecto...

[mpeg @ 00000185e32b4200] buffer underflow st=1 bufi=1466 size=1998

[mpeg @ 00000185e32b4200] Non-monotonous DTS in output stream 0:1; previous: 328415794, current: 9265348; changing to 328415795. This may result in incorrect timestamps in the output file.

Entonces, ¿alguien puede sugerir un método que FUNCIONE tan bien como mi primer ejemplo, pero tomando la lista de archivos de un archivo de texto de entrada?

Respuesta1

Después de mucha experimentación e investigación, descubrí que lo mejor que podía hacer era crear un script de archivo BAT para crear un segundo script de archivo BAT en una variable y guardarlo como un archivo BAt temporal. El archivo BAT construido se puede luego crear con un parámetro "concat:" personalizado, basado en el conjunto de títulos de DVD deseado y la cantidad de archivos descubiertos en el conjunto de títulos. El único inconveniente es que es casi imposible construir una cadena en una variable que contenga el carácter de barra vertical (|). Resolví esto sustituyendo un carácter '@' durante la compilación, y luego utilicé una utilidad de búsqueda y reemplazo de archivos de código abierto para cambiar las instancias '@' a "|". Funciona bien. Tenga en cuenta que estoy usando Windows 10 y FFMPEG versión git-2020-06-26-7447045, descargada e instalada en junio de 2020. A continuación se muestra el archivo por lotes comentado que creé, por lo que si alguien quiere hacer algo similar puede comenzar con esto. Sé que se puede mejorar, ¡pero FUNCIONA (siempre es un buen comienzo)!

::
:: Batch file to automate conversion of a series of VOB files in a DVD
::  titleset into a single MPG file, via FFMPEG. 
:: Pass a name you'd like for the final output movie file in param 1

:: This script needs a a file search and replace utility, and I'm useing
:: SKF (Swiss Army Knife), which is open source and free ...
:: https://sourceforge.net/projects/swissfileknife/

:: Whatever search/replace util you use, you'll have to put it in a
:: 'utilities' folder somewhere in your C: drive, and make sure
:: your system (or USER) PATH variable includes it.

:: Also, unless you have unencrytpted DVD copies to work with, OR a 
:: Decryptor that automatically works in the background (like DVD43),
:: you'll have to start with a program like "1-Click DVD Copy (Pro)".
:: In that case you can put the Resulting VIDEO_TS folder in a temp
:: area on your HD. This will make this batch process run faster, 
:: and eliminate the needs to waste a blank DVD.
 
echo off
SETLOCAL ENABLEDELAYEDEXPANSION

:: Set a path where converted ouptput videos will go
:: Temporary files created by this script will also go here.
set outPath="C:\Users\Public\Videos\Temp"
:: set a path to your DVD. Playable DVDs always have aVIDEO_TS folder
set inPathDVD="Q:\VIDEO_TS"
:: In the event you are making unencrypted copies (maybe with 1-Click), 
:: set that software to put its output files here. In that case,
:: the parameter you pass this script should match the folder name
:: created by that software! 
set inPathHD="C:\Users\Public\Videos\Temp\%1\Video_TS"

:: some variables to construct expecteed files to seach for and gather
set inpTitleSet=VTS_
set inpExt=.VOB
set output=%outPath%\%1.mpg
set outTemp=%outPath%\%1%inpExt%

:: choose whether files come directly from DVD (must be unencrypted!)
:: or defined location on HD
choice /M "Choose Source 1 = DVD  2 = HD Temp Area" /C 12

if ERRORLEVEL 1 set inPath=%inPathDVD%
if ERRORLEVEL 2 set inPath=%inPathHD%

echo input path is: %inPath%
cd /D %inPath%
echo .
echo VOB files from %inpath%...
echo .

:: create filespec for search "VTS_01_*.vob"
set inputFileSpec=%inpTitleSet%*%inpExt% 
dir %inputFileSpec%
echo .
:: select desired titleset. Usually the group with the 
:: biggest file sizes is  the main movie titleset.
:: You'll be entering the digit after "VTS_0"
choice /M "Select Desired Titleset (digit after VTS_): " /C 12345678
echo you picked %ERRORLEVEL%
set inpTitleSet=%inpTitleSet%0%ERRORLEVEL%_
set inputFileSpec=%inpTitleSet%*%inpExt% 

:: use a brute force loop to calculate number of 
:: files matching %inputFileSpec% and display them.
:: Note that the '0' file is usually title/menu information,
:: and is skipped by making the %start% var '1'

echo files selected...
echo .
set start=1
:loop0
set tmp=%inpTitleSet%%start%%inpExt%
IF EXIST %tmp% (
echo %tmp%
set /A start=start+1
GOTO loop0
)
set /A count=%start%-1
echo .
:: confirm total files
echo Total Files = %count%

:: safety exit, in odd event where no movie files found
if %count% NEQ 0 GOTO continue1
echo .
echo Must Exit... no Files Found.
goto exit
:continue1

:: Build string containing of file names for FFMPEG "concat:" parameter.
:: Another Brute force loop. Again file *0.VOB will be skipped, 
:: by making loop start=1:: 

:: set an 'empty' variable
set cc=
set start=1
:: create a temp substitute for the pipe "|" character, 
:: because | can't be cant be used in a script (^| or similar
::  constructs just won't work here). So I'll use '@' and change it 
:: later with a file search/replace utility.
set mypipe=@

:loop1
set tmp=%inpTitleSet%%start%%inpExt%
if %start% EQU %count% set mypipe=
IF EXIST %tmp% (
set cc=%cc%%inp%%tmp%%mypipe%
set /A start=start+1
GOTO loop1
)

:: create whole FFMPEG command as a string
set ffm=ffmpeg -i "concat:%cc%" -f DVD -c copy %output%

:: put it in a tmp batch file
set cmdfile=tmp.bat
echo %ffm%  > %outPath%\%cmdfile%

:: now use SKF to replace the @ chars with |
:: if you have another search/replace utility, feel free to use it.
sfk replace %outPath%\%cmdfile% "/@/|/" -yes -quiet

:: prove string in batch file looks right. You can delete
:: these two lines if you want.
echo Final command...
type %outPath%\%cmdfile%

:: run the new batch file... Give user chance to start process
@pause
call %outPath%\%cmdfile%

:: delete batch file?
del %outPath%\%cmdfile%
echo .
echo .
echo %output% converted file should be ready

ENDLOCAL
:exit

información relacionada