I'm using ffmpeg to merge videos, I have a bunch *.mp4 and *.m4a with the same name, the manual way to do the conversion is to type the ffmpeg command with the quoted name of the files, I tried to automate and drag and drop both files to merge but I've not being able to pass the file names to variables and then to ffmpeg, I tried this code with quotes, with ! instead of % but no luck, someone know what I'm doing wrong?
#echo off
setlocal ENABLEDELAYEDEXPANSION
set "params=!cmdcmdline!"
set "params=!params:~0,-1!"
set "params=!params:*" =!"
set count=0
for %%G IN (!params!) do (
if %%~xG==.m4a (
set myaudio=%%~G)
if %%~xG==.mp4 (
set myvideo=%%~G )
)
C:\ffmpeg\bin\ffmpeg.exe -y -i "%myaudio%" -i "%myvideo%" -c copy "%myvideo%_new.mp4"
pause
exit
edit: I had wrong syntaxis, as stated on the comments, removing the extra spaces solved the problem
Related
I'm using ffmpeg.exe to process screen captures for a demo using MS Game Bar. Game Bar captures at a high frame rate at high resolution and the files are very large.
Using ffmpeg.exe I can process the files using:
ffmpeg.exe -i file.mpg file_l.mpg
And all is good but I'd like to create a bat file so I can do half a dozen or any in a folder all at once.
My Windows bat skills are poor and I've been trying to get it to work using something like this without success:
for %%f in (*.mp4) do (
ren %%~nf%%~xf !fileNum!%%~xf
set/a fileNum += 1
Can anyone help please
here's one I've used that can perhaps be adapted to meet your needs.
SETLOCAL EnableDelayedExpansion
:: start loop
for %%G in (*.mp3) do (
:: get filename without extension
set OUTPUT=%%~nG
:: pass filename to FFmpeg output
ffmpeg -i %%G !OUTPUT!.wav
:: delete source file
del %%G
)
if your input format and output format are the same, you can do something like this:
SETLOCAL EnableDelayedExpansion
:: start loop
for %%G in (*.mp3) do (
:: get filename with extension
set MYNAME=%%~nxG
:: create temp name
ren !MYNAME! delete1.mp3
:: pass original filename to FFmpeg output
ffmpeg -i delete1.mp3 !MYNAME!
:: delete temp file
del delete1.mp3
)
I am trying to create a for loop that will go through a directory and run an ffmpeg command to all files within that directory. My problem is that some of the files have ! in their name which causes problems when using delayed expansion. I have researched many solutions and none of them are getting me anywhere. Currently I can echo the file names with the ! included, but I cannot seem to pass the file name with the ! into my for loop as the delayed expansion effectively removes the !.
Here is my batch script:
#echo off
setlocal enabledelayedexpansion
for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
set "filename=%%~nxf"
ffmpeg -i "%%f" -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\!filename!"
)
pause
This works fine for all files without the ! in the name. If I use a batch script like this:
#echo off
for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
call :command "%%f"
)
pause
:command
set "fname=%~nx1"
set "fpath=%~dpnx1"
echo %fname%
ffmpeg -i %fpath% -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%"
Then I can get the file names and full paths to echo with the ! included, but the ffmpeg command referencing %fname% and %fpath% returns a No such file or directory message. If I add in SetLocal EnableDelayedExpansion just after the echo off and change the ffmpeg string to have ! instead of %, then I again get the No such file or directory message.
I know that in a FOR loop everything in the DO part of the statement gets expanded before everything else which is why I need to use delayed expansion, but how can I use that and still use file names that contain !? Is there a way to get the first batch to accept files that have the ! in the name?
The simplest solution is not to use delayed expansion.
#echo off
setlocal enableextensions disabledelayedexpansion
set ffmpegArguments=-vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001
for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
ffmpeg -i "%%f" %ffmpegArguments% "E:\Converted\%%~nxf"
)
pause
There is not any need to assign the information retrieved from the for replaceable parameter to a variable, just use the retrieved value
:command
SETLOCAL DISABLEDELAYEDEXPANSION
set "fname=%~nx1"
set "fpath=%~dpnx1"
echo %fname%
ffmpeg -i %fpath% -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%"
ENDLOCAL
GOTO :EOF
should fix your problem by disabling the delayedexpansion while ! is a literal character.
I add the goto out of habit so I don't have to remember about it if I add a new subroutine.
I posted too soon! I finally got it working!
It turns out that in the second script using %fpath% for the ffmpeg input only gets the filepath up until the first space where it truncates (because I didn't have it in quotes). After putting %fpath% in quotes, the script works with files that have ! in the name! Here it is:
#echo off
for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
call :command "%%f"
)
:command
set "fname=%~nx1"
set "fpath=%~dpnx1"
ffmpeg -i "%fpath%" -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%"
I'm trying to create a script to run a program that receives as an argument the name of a file. The problem I'm having is that the program doesn't work if the filename has special characters in it.
I found this post which helped me a bit. With a few modifications on that script I'm able to use the program with filenames containing [ and ].
However, there are still some other special characters that cause the program to not run. Is it possible to create a batch for all special characters? If not, I would at least need to be able to parse not only [ and ], but ' as well.
This is what I have working at the moment. How can I at least add ' to this?
if not exist "mp4\" mkdir mp4
setlocal disableDelayedExpansion
for %%f in (*.mkv) do (
set _a=%%~nf
set _c=%%f
setlocal enableDelayedExpansion
set _b=!_a:[=\[!
set _name=!_b:]=\]!
set _d=!_c:[=\[!
set _fullname=!_d:]=\]!
"SOMEPATH\ffmpeg\bin\ffmpeg.exe" -i "%%f" -vf subtitles="!_name!.mkv:si=1" -c:v h264_qsv -c:a copy -map 0:v:0 -map 0:a:1 -q:v 6 -look_ahead 0 "mp4/%%~nf.mp4"
endlocal
)
endlocal
pause
If you could explain the reasoning behind stuff that would be cool as well. I don't understand much about scripting, but I would like to understand what's going on in this batch...
Oh, and here is the documentation for escaping characters in this program.
My organization uses batch files to perform queries on our database, and I am presented with a situation in which I need to perform a query which would be much too large to do all at once. So what I've done is modified a batch file to loop through a text file and query each line individually and append the results to the output file.
The problem is when I echo the query variable it reads exactly as expected, but when I pass it to ogr in place of the sql string it seems to be blank. I'm not sure if I'm doing something wrong, or if what I'm trying to do just isn't possible. Can anyone clarify what's going on here?
SET Path=\\my\path\blah\gdal\bin
SET GDAL_DATA=\\my\path\blah\gdal\data
#echo off
SET "file=C:\filepath.txt"
SET /A i=0
REM put file into array line by line
for /F "usebackq delims=" %%a in ("%file%") DO (
set /A i+=1
call set array[%%i%%]=%%a
call set n=%%i%%
)
REM Loop through array entries
for /L %%i in (1,1, %n%) DO (
REM Create SQL String
call set "queryStart="SELECT * FROM _tablename WHERE _fieldname IN ('"
call set uid=%%array[%%i]%%
call set "queryEnd=')""
call set call set "fullQuery=%%queryStart%%%%uid%%%%queryEnd%%"
REM Database Request
ogr2ogr -skipfailures -update -append -s_srs EPSG:4326 -t_srs EPSG:4326 -f "FileGDB" C:\blah\MyExport.gdb PG:"dbname=instagram host=hostservername user=username password=password" -sql %fullquery% -nln "LayerName" -nlt POINT --config FGDB_BULK_LOAD yes
)
pause;
SET Path=\\my\path\blah\gdal\bin;%PATH%
SET GDAL_DATA=\\my\path\blah\gdal\data
#echo off
SET "file=C:\filepath.txt"
SET /A i=0
set "queryStart=SELECT * FROM _tablename WHERE _fieldname IN ^('"
set "queryEnd='^)"
REM put file into array line by line
for /F "usebackq delims=" %%a in ("%file%") DO (
ogr2ogr -skipfailures -update -append -s_srs EPSG:4326 -t_srs EPSG:4326 ^
-f "FileGDB" C:\blah\MyExport.gdb PG:"dbname=instagram host=hostservername user=username password=password" ^
-sql "%queryStart%%%a%queryEnd%" ^
-nln "LayerName" -nlt POINT --config FGDB_BULK_LOAD yes
)
It is not a good idea to remove all elements from path
There is no need to define the start and end of the query in each iteration
You can have problems with the parenthesis in the query, escape them
There is no need for the array, so directly read the file and use the read value in the query.
I have splitted the lines to better read the code. I don't know if ogr2ogr will complain
Not all the changes are needed, of course, just to make it more readable.
And, after all this, if i have to bet, your problem is in the parenthesis. But i can not test it.
Okay, a brief explanation of what I am doing: I use Windows Media Center (Windows 7) to record Jeopardy every evening. I then use Handbrake to convert the .wtv files to .mkv files and then transfer them to my NAS so I can watch them later using Plex Media Server/Center. Rather than doing this "by hand", I'm trying to automate the process using a batch file as a scheduled task. Initially, I had set up a script so that I could right-click > Send To > convert.bat and it would initiate the command-line interface for Handbrake and convert the file, move the output to my NAS, and delete the original file (worked great).
Now, what I'm doing is initiating the batch script as a scheduled task and looping through the contents of my "recorded tv" directory and looping through any .wtv files to convert/move/delete them.
The problem lies in the fact that Windows Media Center correctly names the Jeopardy files with the "!" in them (Eg: Jeopardy!_KHQ_2012_12_04_21_12_12.wtv), which completely bricks my script. The "Send To" batch file worked great, but when I loop through the *.wtv files in the directory, it returns all the filenames with the "!" stripped out which means I can't do squat with them. Files without "!" do process without a hitch.
Thanks in advance to anyone who can get me pointed in the right direction! (and if you happen to see any other areas where this script could be improved, that's fine too...)
Here is the basic code that I am attempting to use:
#echo off
setlocal ENABLEDELAYEDEXPANSION
SET count=0
SET getFolder=C:\Users\Public\Recorded TV\
SET ripFolder=C:\Rips\
SET putFolder=Z:\Videos\Recorded TV\
FOR %%F IN ("%getFolder%*.wtv") DO (
SET /A count=!count!+1
REM DETERMINE OUTPUT FILENAME
for /f "tokens=5,6,7,8,9,10 delims=\_" %%a in ("%%F") do (
set show=%%a
set station=%%b
set year=%%c
set month=%%d
set day=%%e
set hour=%%f
REM GENERATE OUTPUT NAMING CONVENTION
set output=!show! s!year!e!month!!day! !hour!
)
REM PROCESS WITH HANDBRAKE CLI
"C:\Program Files\Handbrake\HandBrakeCLI.exe" -i "%%F" -t 1 -c 1 -o %ripFolder%!OUTPUT!.mkv -f mkv --deinterlace="fast" --crop 58:60:2:2 --strict-anamorphic -e x264 -q 20 --vfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0 --gain=0 --audio-copy-mask none --audio-fallback ffac3 -x ref=1:weightp=1:subq=2:rc-lookahead=10:trellis=0:8x8dct=0 --verbose=1
REM MOVE CONVERTED FILE TO NAS
copy "%ripFolder%!OUTPUT!.mkv" "%putFolder%"
REM DELETE ORIGINAL
del "%%F"
REM DELETE LOCAL RIP
del "%ripFolder%!output!.mkv"
)
echo %count% files processed
pause
ENDLOCAL
As you have recognized, the exclamation mark is stripped before you can escape it.
That's because you expand the FOR-loop variable %%F while delayed expansion is enabled, and the exclamation mark tries to expand a variable.
You need to toggle the delayed expansion here, as the variable contents are safe when using with delayed expansion, but to get the value you need the disabled mode.
#echo off
setlocal DisableDelayedExpansion
SET count=0
FOR %%F IN ("%getFolder%*.wtv") DO (
set "orgFile=%%F"
SET /A count+=1
REM DETERMINE OUTPUT FILENAME
for /f "tokens=5,6,7,8,9,10 delims=\_" %%a in ("%%F") do (
set show=%%a
set station=%%b
set year=%%c
set month=%%d
set day=%%e
set hour=%%f
setlocal EnableDelayedExpansion
REM GENERATE OUTPUT NAMING CONVENTION
set output=!show! s!year!e!month!!day! !hour!
)
REM PROCESS WITH HANDBRAKE CLI
"C:\Program Files\Handbrake\HandBrakeCLI.exe" -i "%%F" -t 1 -c 1 -o %ripFolder%!OUTPUT!.mkv -f mkv --deinterlace="fast" --crop 58:60:2:2 --strict-anamorphic -e x264 -q 20 --vfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0 --gain=0 --audio-copy-mask none --audio-fallback ffac3 -x ref=1:weightp=1:subq=2:rc-lookahead=10:trellis=0:8x8dct=0 --verbose=1
REM MOVE CONVERTED FILE TO NAS
copy "%ripFolder%!OUTPUT!.mkv" "%putFolder%"
REM DELETE ORIGINAL
del "!orgFile!"
REM DELETE LOCAL RIP
del "%ripFolder%!output!.mkv"
endlocal
)