Parse ffmpeg output into batch variable - batch-file

help please.
I am on Windows command line and I want ffmpeg error returned as variable.
Tried many things, still not working.
#echo off&setlocal disabledelayedexpansion
SET S="path\to\ffmpeg.exe" -hide_banner -i InputFile.FLV -vframes 1 -an -s 400x222 -ss 30 OutputFile.jpg
!S!
for /f "usebackq delims=" %%A in ('!S!') do set var=%%A
echo !var!
The result is that the statement !S! produces the correct output on the console (InputFile.FLV: No such file or directory) but does not put that into the variable. The output of echo !var! statement simply shows as "path\to\ffmpeg.exe" -hide_banner -i InputFile.FLV -vframes 1 -an -s 400x222 -ss 30 OutputFile.jpg
How do I get the output of !S! into !var!?

The command setlocal disabledelayedexpansion explicitly disables delayed expansion and so !S! is not expanded delayed at all. For that reason the command line with just !S! results in an error message on execution of the batch file and definitely not in output InputFile.FLV: No such file or directory. And last line just outputs the string !var!.
The usage of for option usebackq results in interpreting the string between '...' as string and not as command line to execute with %ComSpec% /c in a background command process. For that reason the string !S! is assigned to variable var.
Therefore it can be expected that batch file was executed with setlocal EnableDelayedExpansion in real to get the outputs as written in question.
This not tested batch file should work for this task.
#echo off
set "var="
for /F delims^=^ eol^= %%I in ('""path\to\ffmpeg.exe" -hide_banner -i InputFile.FLV -vframes 1 -an -s 400x222 -ss 30 OutputFile.jpg 2>&1"') do set "var=%%I"
if defined var set var
Command FOR with option /F without using option usebackq and with a command line defined between the two ' executes in background %ComSpec% /c and the string between the two ' appended. So executed with Windows being installed in C:\Windows is:
C:\Windows\System32\cmd.exe /c ""path\to\ffmpeg.exe" -hide_banner -i InputFile.FLV -vframes 1 -an -s 400x222 -ss 30 OutputFile.jpg 2>&1"
The started Windows command processor instanced running in background removes in this case first and last " before executing the remaining command line:
"path\to\ffmpeg.exe" -hide_banner -i InputFile.FLV -vframes 1 -an -s 400x222 -ss 30 OutputFile.jpg 2>&1
ffmpeg.exe not installed by me at all outputs information like this one as far as I know to handle STDERR (standard error) instead of STDOUT (standard output). But FOR captures just output written to handle STDOUT of started command process. For that reason 2>&1 is needed to redirect output written to handle STDERR of background command process by ffmpeg.exe to handle STDOUT of background command process for being also captured by FOR of command process which is processing the batch file.
With FOR options argument string delims^=^ eol^= an empty list of string delimiters and no end of line character is defined to really get always the entire line as captured by FOR assigned to specified loop variable I. The two options are specified here by way of an exception not enclosed in " as otherwise it is not possible to define an empty list of delimiters and no end of line character. The two equal signs and the space must be escaped with caret character ^ to be interpreted as literal characters and not as argument string separators because of not being enclosed in a double quoted argument string.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
cmd /? ... explains how double quotes in string(s) after option /C or /K are interpreted by Windows command processor and when a file name (or any other argument string) must be enclosed in " on containing a space or one of these characters &()[]{}^=;!'+,`~<|>.
for /?
if /?
set /?
See also the Microsoft article about Using command redirection operators.

Related

How to escape pipe in curl in a batch script?

I have a Windows batch script like this:
#echo off
setlocal EnableDelayedExpansion
SET fruit1=apple
SET fruit2=banana
SET "payload={\"name\":\"value\",\"name\":\"%fruit1%^|%fruit2%\"}"
echo %payload%
curl -X POST -H "Content-Type: application/json" -d "%payload%" "<serverURL>"
endlocal
The output is:
{\"name\":\"value\",\"name\":\"apple|banana\"}
Cannot find the specified path
So Curl is not doing anything, that error message is due to the pipe I guess, while the echoed payload is displayed correctly.
As you can see I already tried escaping the pipe with ^ , and setting EnableDelayedExpansion , but nothing works.
Is there a way to pass the correct payload to curl?
I suggest to use:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "fruit1=apple"
set "fruit2=banana"
set "payload={\"name\":\"value\",\"name\":\"%fruit1%^|%fruit2%\"}"
setlocal EnableDelayedExpansion
echo !payload!
curl.exe -X POST -H "Content-Type: application/json" -d "!payload!" "<serverURL>"
endlocal
endlocal
The environment variables are defined while delayed environment variable expansion is disabled which results in processing each command line with command SET at beginning only once by the Windows command processor.
See also: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
The vertical bar must be escaped nevertheless with a caret character to be interpreted as literal character and not as pipe redirection operator.
Then delayed expansion is enabled and used on referencing the string value assigned to the environment variable payload by using ! around the environment variable name instead of %.
It would be also possible to use in this special case:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "fruit1=apple"
set "fruit2=banana"
set "payload={\"name\":\"value\",\"name\":\"%fruit1%^|%fruit2%\"}"
echo !payload!
curl.exe -X POST -H "Content-Type: application/json" -d "!payload!" "<serverURL>"
endlocal
The three lines defining the three environment variables do not contain an exclamation mark and there is also no other string get from somewhere outside the batch file. For that reason it is possible to enable delayed environment variable expansion with the second command line and let the Windows command processor double process all command lines. The environment variables fruit1 and fruit2 could be referenced in this case also with using delayed expansion by using as fifth command line:
set "payload={\"name\":\"value\",\"name\":\"!fruit1!^|!fruit2!\"}"
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
endlocal /?
set /?
setlocal /?
curl -h or curl --help

get value from cropdetect

I have been able to parse the output of ffmpeg cropdetect with a batch file in Windows 7 to get crop=640:480:0:0 but the process goes too far and processes the last mp4 or mkv file twice.
I run the first for loop to get a list of mkv or mp4 files in the folder and run a process :gin.
The second for loop to run ffmpeg skipping ahead 30 seconds and run cropdetect on only one second of video with the long file of 60 plus entrys of
[Parsed_cropdetect_0 # 0000000002ef8f00] x1:0 x2:1279 y1:0 y2:719 w:1280 h:720 x:0 y:0 pts:1081 t:1.081000 crop=1280:720:0:0
going to tmp.txt
Tail gives me the last line of tmp.txt and outputs to a new text file tmp1.txt
The last for loop looks at tmp1.txt and returns the 14th. token of crop=1280:720:0:0
This is a Zeranoe Windows static build and I have tails for windows installed.
I have tried...
different for loops
for %g in (*.mp4, *.mkv) do set this=%g
for /f "delims=*" %g in ('dir /b /o:n *.mp4, *.mkv') set this=%g
I have also tried to have tail output overwrite the input with tail -1 tmp.txt > tmp.txt
this all works but is not as elegant.
what I have so far,
for /f "delims=*" %%g in ('dir /b /o:-n *.m??') do set cdet=%%g&& call :gin
:gin
ffmpeg -hide_banner -ss 00:0:30.000 -i "%cdet%" -t 1 -vf cropdetect -f null -2>&1 | findstr /c:"crop=" > tmp.txt
tail -1 tmp.txt >tmp1.txt
for /f "usebackq tokens=14" %%a in ("tmp1.txt") do set line=%%a
del tmp*.txt
echo %line%
I would like to see if there is a better way to do this without creating temp files and overwriting already processed files.
for those interested the updated script is:
for /F "eol=| delims=" %%I in ('dir /a-d /b /o:-n *.mkv 2^>nul') do set "cdet=%%I" && call :gin
goto :end
:gin
ffmpeg -hide_banner -ss 00:0:30.000 -i "%cdet%" -t 1 -vf cropdetect -f null - 2>&1 | findstr /c:"crop=" >tmp1.txt
for /f "usebackq tokens=14" %%a in ("tmp1.txt") do set line=%%a
del tmp*.txt
echo %line%
pause
:end
exit /b
The last file is processed twice because of goto :EOF or exit /B is missing after first for loop to avoid a fall through to the command lines of the subroutine after first for finished. See also: Where does GOTO :EOF return to?
The batch file can be optimized most likely with avoiding the subroutine completely according to provided data with using this code:
setlocal EnableExtensions DisableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir *.m?? /A-D-H /B /O-N 2^>nul') do (
for /F "tokens=2 delims==" %%J in ('"ffmpeg.exe -hide_banner -ss 00:0:30.000 -i "%%I" -t 1 -vf cropdetect -f null - 2>&1 | %SystemRoot%\System32\findstr.exe /c:"crop=""') do set "CropData=%%J"
call echo crop=%%CropData%%
)
endlocal
Command FOR with option /F and a command line specified between ' results in starting one more command process in background with %ComSpec% /c and the specified command line. So executed by FOR is with Windows being installed into C:\Windows:
C:\Windows\System32\cmd.exe /c dir *.m?? /A-D-H /B /O-N 2>nul
DIR searches
in current directory
just for non-hidden files because of option /A-D-H (attribute not directory and not hidden)
matching the wildcard pattern *.m??
and outputs in bare format because of option /B just the names of the files without file path
ordered reverse by file name because of option /O-N (for whatever reason).
The file names are output to handle STDOUT (standard output) of background command process. This output is captured by FOR respectively the command process running the batch file.
It is possible that no directory entry matches the specified search criteria resulting in printing an error message by DIR to handle STDERR (standard error) which is redirected by FOR to STDERR of command process running the batch file. This error message can be suppressed by redirecting it to device NUL by started cmd.exe running in background.
Read the Microsoft documentation about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
FOR with option /F processes the captured standard output of started command process line by line after started cmd.exe terminated itself as follows:
Empty lines are always ignored by FOR, but empty lines do not occur here.
A line is split up by default into substrings using normal space and horizontal tab as delimiters and just first space/tab separated string is assigned to specified loop variable I. This line splitting behavior is not wanted in this case as the file names could contain spaces and the entire file name should be assigned to loop variable I and not just the file name part up to first space. For that reason delims= defines an empty list of delimiters to turn off line splitting completely.
Next FOR checks if first substring, i.e. entire file name in this case, starts with default end of line character ; which is a valid character for first character of a file name. For that reason eol=| redefines end of line character to vertical bar which no file name can contain according to Microsoft documentation Naming Files, Paths, and Namespaces.
For each file the outer FOR executes the inner FOR which runs again in background a command process for example with the command line:
C:\Windows\System32\cmd.exe /c "ffmpeg.exe -hide_banner -ss 00:0:30.000 -i "C:\Temp\My vido.mp4" -t 1 -vf cropdetect -f - null 2>&1 | C:\Windows\System32\findstr.exe /c:"crop=""
The started Windows command processor instanced running in background removes in this case first and last " before executing the remaining command line:
ffmpeg.exe -hide_banner -ss 00:0:30.000 -i "C:\Temp\My vido.mp4" -t 1 -vf cropdetect -f - null 2>&1 | C:\Windows\System32\findstr.exe /c:"crop="
ffmpeg.exe outputs information like this one as far as I know to handle STDERR (standard error) instead of STDOUT (standard output). For that reason 2>&1 is needed to redirect output written to handle STDERR of background command process by ffmpeg.exe to handle STDOUT of background command process which is redirected next to STDIN of FINDSTR searching case sensitive for literal string crop= anywhere in a line and outputs the entire line containing this string to STDOUT of started background command process.
Those lines are captured by FOR and processed one after the other as described above. But this time delims== modifies the list of string delimiters to just equal sign character which results in splitting up a line like
[Parsed_cropdetect_0 # 0000000002ef8f00] x1:0 x2:1279 y1:0 y2:719 w:1280 h:720 x:0 y:0 pts:1081 t:1.081000 crop=1280:720:0:0
into just two substrings:
[Parsed_cropdetect_0 # 0000000002ef8f00] x1:0 x2:1279 y1:0 y2:719 w:1280 h:720 x:0 y:0 pts:1081 t:1.081000 crop
1280:720:0:0
Just the second substring is of interest which is the reason for using tokens=2 to get assigned just 1280:720:0:0 to specified loop variable J which is assigned next to environment variable CropData. It is also possible to use the default string delimiters normal space and horizontal tab and assign fourteenth space/tab separated string to specified loop variable J using "tokens=14" which in this case includes crop= in string assigned finally to environment variable CropData.
There are multiple lines output by FINDSTR with crop= and so multiple lines are processed by inner FOR resulting in assigning multiple times crop data to environment variable CropData. That's okay because of wanted are just the last crop data.
The second command executed by outer FOR on each file outputs just the last crop data with the string crop=. The command CALL is used to force Windows command processor to parse the command line echo crop %CropData% as it is already after parsing the entire command block starting with ( and ending with matching ) at end before executing outer FOR a second time to real output the current value of environment variable CropData. See also: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Another solution would be using delayed expansion as shown below.
setlocal EnableExtensions EnableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir *.m?? /A-D-H /B /O-N 2^>nul') do (
for /F "tokens=2 delims==" %%J in ('"ffmpeg.exe -hide_banner -ss 00:0:30.000 -i "%%I" -t 1 -vf cropdetect -f null - 2>&1 | %SystemRoot%\System32\findstr.exe /c:"crop=""') do set "CropData=%%J"
echo crop=!CropData!
)
endlocal
But this solution can be used only if no file name contains one or even more ! as otherwise the exclamation mark(s) in file name would be interpreted as begin/end of an environment variable referenced and so the file name would not be correct passed to ffmpeg.exe.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
cmd /? ... explains how double quotes in string(s) after option /C or /K are interpreted by Windows command processor and when a file name (or any other argument string) must be enclosed in " on containing a space or one of these characters &()[]{}^=;!'+,`~<|>.
echo /?
endlocal /?
findstr /?
for /?
set /?
setlocal /?

How to read and print contents of text file line by line?

So, I have no clue on how to have CMD echo lines from a *.txt text file one at a time with a tiny delay to make it seem like it's processing.
Is this even possible with a batch alone?
I've tried doing research, but I can't find sufficient text manipulation to be able to do this, but I do know how to make a pause between each command and how to do loops.
Let us assume the text file TestFile.txt should be output line by line which is an ANSI encoded text file with just ASCII characters containing this text:
Line 1 is with nothing special. Next line 2 is an empty line.
;Line 3 with a semicolon at beginning.
Line 4 has leading spaces.
Line 5 has a leading horizontal tab.
Line 6 is with nothing special. Next line 7 has just a tab and four spaces if used internet browser does not remove them.
Line 8 is ! with exclamation marks ! in line!
? Line 9 starts with a question mark.
: Line 10 starts with a colon.
] Line 11 starts with a closing square bracket.
The batch file below outputs this text file line by line with one second delay between each line with the exception of second line which is completely empty.
#echo off
title Read line by line with delay
setlocal EnableExtensions DisableDelayedExpansion
rem Use command TIMEOUT by default for 1 second delay. But use
rem PING in case of TIMEOUT does not exist as on Windows XP.
set "DelayCommand=%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK"
if not exist %SystemRoot%\System32\timeout.exe set "DelayCommand=%SystemRoot%\System32\ping.exe 127.0.0.1 -n 2"
for /F "usebackq eol=¿ delims=" %%I in ("TestFile.txt") do (
echo(%%I
%DelayCommand% >nul
)
endlocal
pause
The strange looking character ¿ after eol= is an inverted question mark with hexadecimal Unicode value 00BF used to output third line correct. A line with an inverted question mark at beginning would not be output because of this redefinition of end of line character.
This batch file code is not designed to output any type of text file with any type of character encoding independent on which characters contains the text file. The Windows command line environment is not designed for output of any text file.
It is also possible to use a different, unquoted syntax to specify the FOR options delims, eol and usebackq to define an empty list of delimiters and no end of line character:
#echo off
title Read line by line with delay
setlocal EnableExtensions DisableDelayedExpansion
rem Use command TIMEOUT by default for 1 second delay. But use
rem PING in case of TIMEOUT does not exist as on Windows XP.
set "DelayCommand=%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK"
if not exist %SystemRoot%\System32\timeout.exe set "DelayCommand=%SystemRoot%\System32\ping.exe 127.0.0.1 -n 2"
for /F usebackq^ delims^=^ eol^= %%I in ("TestFile.txt") do (
echo(%%I
%DelayCommand% >nul
)
endlocal
pause
Thanks goes to aschipfl for this alternate syntax of the three FOR options with using escape character ^ to escape the equal signs and spaces in not double quoted options string to get interpreted by cmd.exe the string usebackq delims= eol= as one argument string for for /F.
There is ( instead of a space as usually used to output also correct line 7 with just a tab and some normal spaces. See also DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/. echo/%%I does not correct output line 9 starting with a question mark.
It is not possible to define with an option that FOR does not ignore empty lines. But it is possible with FIND or FINDSTR to output a text file with all lines with a line number at beginning and so having no empty line anymore. The line number is enclosed in square brackets (FIND) or separated with a colon (FINDSTR) from rest of the line. It would be possible to assign to loop variable only the string after first sequence of ] or : after line number which in most cases means the entire line as in text file. But if a line in text file starts by chance with ] or :, FOR would remove this delimiter character too. The solution is this code:
#echo off
title Read line by line with delay
setlocal EnableExtensions DisableDelayedExpansion
rem Use command TIMEOUT by default for 1 second delay. But use
rem PING in case of TIMEOUT does not exist as on Windows XP.
set "DelayCommand=%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK"
if not exist %SystemRoot%\System32\timeout.exe set "DelayCommand=%SystemRoot%\System32\ping.exe 127.0.0.1 -n 2"
for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "TestFile.txt" 2^>nul') do (
set "Line=%%I"
setlocal EnableDelayedExpansion
echo(!Line:*:=!
endlocal
%DelayCommand% >nul
)
endlocal
pause
FINDSTR searches in the specified file with the regular expression ^ for matching lines. ^ means beginning of a line. So FINDSTR does not really search for a string in the lines of the file because of every line in a file has a beginning, even the empty lines. The result is a positive match on every line in the file and therefore every line is output by FINDSTR with the line number and a colon at beginning. For that reason no line processed later by for /F is empty anymore because of all lines start now with a line number and a colon, even the empty lines in the text file.
2^>nul is passed to cmd.exe started in background as 2>nul and results in redirecting an error message output by FINDSTR to handle STDERR to the device NUL to suppress the error message. FINDSTR outputs an error message if the file to search does not exist at all or the file cannot be opened for read because of missing NTFS permissions which allow that or because of the text file is currently opened by an application which denies the read access to this file as long as being opened by the application.
cmd.exe processing the batch file captures all lines output by FINDSTR to handle STDOUT of cmd.exe started in background and FOR processes now really all lines in the file after FINDSTR finished and the background command process closed itself.
The entire line with line number and colon output by FINDSTR executed in a separate command processes started by FOR with %ComSpec% /c and the command line within ' as additional arguments is assigned to loop variable I which is assigned next to environment variable Line.
Then delayed expansion is enabled as needed for next line which results in pushing address of current environment variables list on stack as well as current directory path, state of command extensions and state of delayed expansion before creating a copy of the current environment variables list.
Next the value of environment variable Line is output, but with substituting everything up to first colon by nothing which results in the output of the real line as stored in text file without the line number and the colon inserted at beginning by FINDSTR.
Finally the created copy of environment variables list is deleted from memory, and previous states of delayed expansion and command extension are popped from stack and set as well as the current directory path is set again as current directory and previous address of environment variables list is restored to restore the list of environment variables.
It is of course not very efficient to run for each line in text file the commands setlocal EnableDelayedExpansion and endlocal doing much more than just enabling/disabling delayed expansion, but this is necessary here to get lines with an exclamation mark correct assigned to environment variable Line and process next correct the value of Line. The efficiency loss is not really problematic here because of the delay of one second between output of each line.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
endlocal /?
findstr /?
for /?
if /?
ping /?
rem /?
set /?
setlocal /?
Despite your question being off topic, I have decided to include this because, there are already two answers and it can be achieved using a single line.
From a batch file:
#For /F Tokens^=1*Delims^=]^ EOL^= %%A In ('Find /N /V ""^<"C:\test.txt"') Do #Echo(%%B&>Nul PathPing 127.0.0.1 -n -q 1 -p 450
From the Command Prompt:
For /F Tokens^=1*Delims^=]^ EOL^= %A In ('Find /N /V ""^<"C:\test.txt"') Do #Echo(%B&>Nul PathPing 127.0.0.1 -n -q 1 -p 1350
Both examples do not omit empty lines from your source file, C:\test.txt, which can be changed as required.I have used PathPing for the 'tiny delay', because it seems more controllable; to adjust the delay all you need to do is change the last number until you find your most pleasing output.
Give a try for this batch script :
#echo off
Title Read line by line with delay
set "InputFile=TestFile.txt"
set "delay=1" Rem Delay one seconds, you can change it for your needs
setlocal enabledelayedexpansion
for /f "tokens=*" %%A in ('Type "%InputFile%"') do (
set /a N+=1
set "Line[!N!]=%%A"
)
for /l %%i in (1,1,%N%) do (
echo !Line[%%i]!
Timeout /T %delay% /nobreak>nul
)
pause

set variable and call result during FOR loop; batch script windows

I have read several posts here on Stackoverflow about binding a variable during a FOR loop. While I figure most of the help provided here has been for Linux/Unix, I'm reaching out for help with batch scripting in Windows. My main goal is to extract the "date created" from a mp4-file and "overlay the date on my video" using ffmpeg (and or ffprobe).
I have experimented a lot, but my latest attempt has been trying to bind the result from ffprobe onto a variable, and use the variable later. My latest and simplest attempt looks like this:
SETLOCAL ENABLEDELAYEDEXPANSION
for %%a in ("*.mp4") do (
for /F "tokens=*" %%G in ('ffprobe -v quiet %%a -print_format compact -show_entries format_tags=creation_time') do (
set DateC=%%G
echo !DateC!)
)
I was hoping to be able to print the tag result from ffprobe using that code, but apparently not. So helping me bind that variable, and how to call it again later inside the following code snippet in Windows, would be deeply appreciated:
ffmpeg -i %%a -filter_complex "drawtext=fontfile=/Windows/Fonts/Arial.ttf:x=28:y=650:fontsize=45:fontcolor=white:box=1:boxcolor=black#0.4:text='!DateC!'" -c:a copy output.mp4
I must also mention I've seen the following code on StackOverflow:
ffmpeg -i %%a -filter_complex "drawtext=fontfile=/Windows/Fonts/Arial.ttf:x=28:y=650:fontsize=45:fontcolor=white:box=1:boxcolor=black#0.4:text='%{metadata\:creation_time}'" -c:a copy output.mp4
But I have the same problem making Windows recognize and print the metadata.
I am certain the file in question contains this metadata.
I suggest this not tested code for the batch file:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for %%a in ("*.mp4") do (
for /F "delims=" %%G in ('ffprobe.exe -v quiet "%%a" -print_format compact -show_entries format_tags^=creation_time 2^>^&1') do (
set "DateC=%%G"
echo !DateC!
)
)
endlocal
The inner FOR runs in a separate command process started with cmd /C the command line:
ffprobe.exe -v quiet "%%a" -print_format compact -show_entries format_tags=creation_time 2>&1
"%%a" is already replaced by name of current *.mp4 file. The double quotes are necessary in case of current *.mp4 file name contains a space or one of these characters &()[]{}^=;!'+,`~.
It is necessary to escape the equal sign with ^ in arguments list to get the command line correct passed to cmd.exe started by FOR in background.
2>&1 results in redirecting output written to handle STDERR to handle STDOUT because of FOR captures only everything written to STDOUT of the started command process.
The redirection operators > and & must be escaped with caret character ^ on FOR command line to be interpreted as literal characters when Windows command interpreter processes this command line before executing command FOR which executes the embedded ffprobe.exe command line in the separate command process started in background.
I don't have ffprobe.exe and ffmpeg.exe installed, but I think those console applications write information about files to handle STDERR (standard error) instead of STDOUT (standard output) which is the reason for using 2>&1 to get the wanted information captured by FOR and assigned to an environment variable.
"tokens=*" is the same as "delims=". Both result in getting the entire line captured by FOR assigned to loop variable G without splitting it up into substrings (tokens) using space/tab as delimiters, except the line starts with a semicolon in which case FOR would ignore that line completely for processing because of internal default eol=;.

Batch file CURL String with Spaces and Special Characters

I'm trying to get a string from an url using a batch file.
String example:
e-e --ser u.g --p 3 --f 0 x,ss
I am using the command below to CURL output directly to a variable:
FOR /F %%I IN ('curl.exe -s -S %URL%') DO (SET W=%%I)
The problem is, when I echo the variable [W] after the command runs, most of the string is missing...
e-e
What is the best method to get around this issue?
By default, the FOR /F command delimits the output based on a space and tab. That is stated in the help file. To keep that from happening use the DELIMS option to tell the FOR command to not use any delimiters.
FOR /F "delims=" %%I IN ('curl.exe -s -S %URL%') DO (SET W=%%I)

Resources