I'm working on a simple batch script that loops over files in a directory and process them with ffmpeg. for readability purposes, I want to indent the ffmpeg output 4 spaces, but I cannot come up with a way that works.
@echo off
for %%a in (%~dp0rawVideo\*.MP4) do (
if exist %~dp0rawAudio\%%~na.wav (
echo Already Processed :
echo %%a
) else (
echo Processing :
echo %%a
echo|set /p leadingSpace="# "
ffmpeg -c:v h264 -threads 24 -i %%a -map_channel 0.1.0 -map_channel -1 -y -v quiet -stats %~dp0rawAudio\%%~na.wav
)
echo(
)
pause
If I just do this i get nothing, because I've read windows strips leading white spaces.
echo|set /p leadingSpace=" "
I tried what I think is the backspace trick as well, but it didn't work. Is there no way of doing this?
1st solution
Here's a way to run your command and prefix each line outputted by a prefix.
Simple example without arguments:
@echo off
for /F "delims=" %%a in ('ffmpeg.exe 2^>^&1') do echo # %%a
issues:
# ffmpeg version N-80980-g7af44ce Copyright (c) 2000-2016 the FFmpeg developers
# built with gcc 5.4.0 (GCC)
# configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-li
bmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-libebur128 --enable-fontconfig --enabl
e-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable
-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug -
-enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enab
le-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-li
bspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-l
ibvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --en
able-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
# libavutil 55. 28.100 / 55. 28.100
# libavcodec 57. 50.100 / 57. 50.100
# libavformat 57. 41.100 / 57. 41.100
# libavdevice 57. 0.102 / 57. 0.102
# libavfilter 6. 47.100 / 6. 47.100
# libswscale 4. 1.100 / 4. 1.100
# libswresample 2. 1.100 / 2. 1.100
# libpostproc 54. 0.100 / 54. 0.100
# Hyper fast Audio and Video encoder
# usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
# Use -h to get full help or, even better, run 'man ffmpeg'
it redirects standard error to standard output (so error messages are also prefixed) and uses empty delimiter, so %%a
is the full line.
Since you are called each time a line is issued, it is easy to echo it the way you want.
Of course it also works if the command issues just one line.
2nd solution
Since you only have one line, an alternative would be to use a temporary file to get the output of ffmpeg
, then assign a variable interactively with this file redirected as input. Then echo it as you want:
ffmpeg -c:v h264 -threads 24 -i %%a -map_channel 0.1.0 -map_channel -1 -y -v quiet -stats %~dp0rawAudio\%%~na.wav> %TEMP%\tmpf
set /P ffmpegout=<%TEMP%\tmpf
echo %ffmpegout%
This is a pure Batch file method to create a file with any number of spaces and no line feed at end, so it may be displayed via type spaces.txt
before a set /P
command in order to show leading spaces:
@echo off
setlocal
call :createFourSpaces
type fourSpaces.txt
set /P "=After the spaces" < NUL
echo/
exit /B
:createFourSpaces
for %%X in (^"^
% Do NOT remove this line %
^") do set /P "=X%%~X " > fourSpaces.tmp <NUL
findstr /V "X" fourSpaces.tmp > fourSpaces.txt
del fourSpaces.tmp
exit /B
You could pipe the output into any utility that provides search/replace capability. There isn't a native Windows batch command available, but you could use something like JREPL.BAT - a regular expression text processing utility. JREPL.BAT is pure script (hybrid batch/JScript) that runs natively on any Winidows machine form XP onward - no 3rd party exe file is required. Full documentation is available from the command line via jrepl /?
, or jrepl /??
for paged help.
@echo off
for %%a in (%~dp0rawVideo\*.MP4) do (
if exist %~dp0rawAudio\%%~na.wav (
echo Already Processed :
echo %%a
) else (
echo Processing :
echo %%a
ffmpeg -c:v h264 -threads 24 -i %%a -map_channel 0.1.0 -map_channel -1 -y -v quiet -stats %~dp0rawAudio\%%~na.wav | jrepl "^" " "
)
echo(
)
pause
There is a significant delay each time JREPL is called because the CSCRIPT engine must be instantiated, and the JScript must be compiled. Once started, the utility is very fast. But in this case, the fractional second delay for each iteration could be irritating.
Performance can be dramatically improved if you pipe the entire FOR loop output through a single instance of JREPL. The only trick is to structure the search to only match lines that need to be prefixed.
Here I assume that ffmpeg always puts a non-space character in the first position of each line of output, and the ffmpeg output never contains "Process"
@echo off
(
for %%a in (%~dp0rawVideo\*.MP4) do @(
if exist %~dp0rawAudio\%%~na.wav (
echo Already Processed :
echo %%a
) else (
echo Processing :
echo %%a
ffmpeg -c:v h264 -threads 24 -i %%a -map_channel 0.1.0 -map_channel -1 -y -v quiet -stats %~dp0rawAudio\%%~na.wav
)
echo(
)
) | jrepl "^(?=[^ ])(?!.*Process)" " "
pause