0

I'm trying to write a Windows batch file that uses ffmpeg to convert whole folders with old *.flv videos into *.mp4 videos.

The batch file more or less works, but I want to do some test before deleting the source file. One of these test is that the output file should be at least 2/3 of the original file, but I can't get it to work.

Here's my bat file (with all the debugging echo lines included):

@echo off

setlocal EnableExtensions EnableDelayedExpansion

::-------------------------------------------------------------------------------------
:: get options and folder path
set opzione=%~1%
set cartella=%~2%
:: who's who?
if "%opzione:~3,1%"=="" (
    echo.
) else (
    if "%opzione:~0,1%"=="/" (
        echo.
    ) else (
        set opzione=%~2%
        set cartella=%~1%
    )
)
::echo.
::echo Cartella = %cartella%
::echo Opzione = %opzione%
::echo.



::-------------------------------------------------------------------------------------
:Check_path
    set FLV_FOLDER="%cartella%"

    if %FLV_FOLDER% == "" ( 
        echo ... Invalid
        goto :uscita
    ) else (
        echo ... OK.
    )

::-------------------------------------------------------------------------------------
:Check_Options (STILL W.I.P.)
    set Lista=0
    set Convert=0
    set Delete=0

    if "%opzione%"=="/c" (set Convert=1)
    if "%opzione%"=="/l" (set Lista=1)
    if "%opzione%"=="/d" (set Delete=1)

::echo Lista = %Lista%



::-------------------------------------------------------------------------------------
:Loop_path
@cls
echo Looping all .flv files in %FLV_FOLDER%...

    for /R %FLV_FOLDER% %%a IN (*.flv) do call :Converting_Function "%%a"
    goto :uscita



::-------------------------------------------------------------------------------------
:Converting_Function
    set infile="%~1"
    set outfile="%~dpn1.mp4"

    set outsize=0
    set insize=0
    set minsize=0

    if not %Lista%==0 goto :just_list

    echo Converting %infile% to %outfile%
    ffmpeg -v error -i %infile% -c copy -copyts %outfile%

    ::....................CHECKS........................................................
echo Errors from ffmpeg?
    if errorlevel 1 goto :error_ffmpeg

echo Do the outfile exist?
    if not exist %outfile% goto :error_exist

echo Is outfile big enough? 
    :: (say yes if outfile size > infile size*2/3)
    for /f %%S in (%outfile%) do set "outsize=%%~zS"
echo %outfile% size is %outsize%
    for /f %%S in (%infile%) do set insize=%%~zS
echo %infile% size is %insize%
    set /A "minsize=(%insize%*3)/2"
echo minsize is %minsize%

    if not %outsize% GTR %minsize% goto :error_size
    ren "%~1" "%~n1.todelete"
::               del /q %infile%
    goto :eof
:error_ffmpeg
    echo Convertion error
    pause
    if exist %outfile% del /q %outfile%
    goto :eof
:error_exist
    echo %outfile% does not exist
pause
    goto :eof
:error_size
    echo Size of %outfile% is 0
pause
    goto :eof
:just_list
    echo %infile%
    goto :eof

:uscita
pause

This is the output:

Converting "T:\C++Stuffs\_PROVACONV_\Monaco - Machine_#1 - Monday Morning.flv" to "T:\C++Stuffs\_PROVACONV_\Monaco - Machine_#1 - Monday Morning.mp4"
[flv @ 0000000000577320] Packet mismatch 107347968 1638 1638
Errors from ffmpeg?
Do the outfile exist?
Is outfile big enough?
"T:\C++Stuffs\_PROVACONV_\Monaco - Machine_#1 - Monday Morning.mp4" size is
"T:\C++Stuffs\_PROVACONV_\Monaco - Machine_#1 - Monday Morning.flv" size is
Operando mancante.
minsize is 0
0 non atteso.
D:\ffmpeg-20170204-b1e2192-win64-static\bin>

Operando mancante means Missing Operand, 0 non atteso means Unexpected 0

Why do I not have the file size in the variables? What is the missing operand?

Mofi
  • 38,783
  • 14
  • 62
  • 115
Parduz
  • 537
  • 4
  • 20
  • 1
    Why do you use `for /F` to determine the file size? `for /F` is intended to read the file content; you should use `for` without the `/F` switch instead... – aschipfl Sep 18 '17 at 16:33
  • That was the problem! I used it 'cause i googled and used the accepted answer of a similar question. – Parduz Sep 20 '17 at 11:48
  • I wonder why this question was downvoted... while my question could be stupid, i've done my search, done my attempt, posted my code, not asked for a "do it for me" answer.... – Parduz Sep 20 '17 at 11:51

1 Answers1

2

The environment variables infile and outfile are defined with file name being enclosed in double quotes. That is not recommended as explained in answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? But it is valid and works here as expected.

The command line to get file size of output file

for /f %%S in (%outfile%) do set "outsize=%%~zS"

is processed before execution by Windows command interpreter for example to

for /f %S in ("C:\Path\File Name.mp4") do set "outsize=%~zS"

It can be read on executing in a command prompt window for /? that for /F interprets the set (string between round brackets) as string to process if enclosed in double quotes except the option usebackq is used which is not done here. For that reason FOR splits up the string C:\Path\File Name.mp4 into tokens using space/tab as delimiters and assigns the first token to loop variable S. So assigned to S for the example is C:\Path\File. The file size for this file can't be determined by Windows command interpreter as this file does not exist.

The solution is using FOR without option /F:

for %%S in (%outfile%) do set "outsize=%%~zS"

And the command line to get file size of input file

for /f %%S in (%infile%) do set insize=%%~zS

can be replaced by

set "insize=%~z1"

The help output on running in a command prompt window call /? explains this argument modifier for getting the size of a file passed as first argument to the batch file on calling it.


The help output on running set /? explains that in arithmetic expressions the current values of environment variables can be referenced by specifying the environment variables with just their names without using % or !. This works even within a command block beginning with ( and ending with matching ).

The command line with the arithmetic expression

set /A "minsize=(%insize%*3)/2"

can result on insize not being defined in execution of

set /A "minsize=(*3)/2"

This explains the error message because there is indeed missing the left operand for the multiplication.

The solution is using the arithmetic expression as recommended by help of command SET.

set /A "minsize=(insize*3)/2"

This arithmetic expression never fails on evaluation. In case of environment variable insize is not defined, it is replaced by 0 on evaluation of the arithmetic expression as explained by the help.

See also Debugging a batch file.

And please note that Windows command interpreter supports only arithmetic expressions with 32-bit signed integer values. So video files with a file size of 2 GiB or more cannot be correct processed by your batch code.

Mofi
  • 38,783
  • 14
  • 62
  • 115