I can use the following to retrieve the audio and video codec and the video frame height:
ffprobe -v quiet -show_entries stream=index,codec_name,height -of csv input.mp4
But the output is on two lines and includes text that I don't need like so:
stream,0,h264,720
stream,1,mp3
The only output I want is to be in the form of:
mp3,h264,720
I've tried using -show_entries twice in the same command line, but it ignores the first call every time. I've also tried using
ffprobe -v quiet -select_streams v -show_entries stream=codec_name,height, -select_streams a -show_entries stream=codec_name
but that doesn't do anything.
How can I get the simplified output as specified above?
After our conversation in the comments, I think something like this is what you're looking for. It's a Batch + JScript hybrid script. I'm using JScript to parse and objectify the JSON output by ffprobe
. Salt to taste, and remove echo
from line 31 when you're ready for the script to act.
@if (@CodeSection == @Batch) @then
@echo off & setlocal & goto run
:usage
echo Usage: %~nx0 infile outfile
echo This script re-encodes videos to x265 + AAC encoding.
exit /b
:run
if "%~2"=="" goto usage
if not exist "%~1" goto usage
set ffprobe=ffprobe -v quiet -show_entries "stream=codec_name,height" -of json "%~1"
for /f "delims=" %%I in ('%ffprobe% ^| cscript /nologo /e:JScript "%~f0"') do set "%%~I"
if %height% lss 720 (
echo Video is ^< 720p. Not worth it.
exit /b
)
set "pre=-hide_banner -fflags +genpts+discardcorrupt+fastseek -analyzeduration 100M"
set "pre=%pre% -probesize 50M -hwaccel dxva2 -y -threads 3 -v error -stats"
set "global="
set "video=-c:v libx265 -crf 22 -preset fast"
set "audio=-c:a libfdk_aac -flags +qscale -global_quality 4 -afterburner 1"
if defined hevc if defined aac (
echo Already in x265 + AAC format.
exit /b
)
if defined aac (
echo Already has AAC audio. Re-encoding video only.
set "audio=-c:a copy"
) else if defined hevc (
echo Already has x265 video. Re-encoding audio only.
set "video=-c:v copy"
)
echo ffmpeg %pre% -i "%~1" %global% %video% %audio% "%~2"
goto :EOF
@end // end Batch / begin JScript
var stdin = WSH.CreateObject('Scripting.FileSystemObject').GetStandardStream(0),
htmlfile = WSH.CreateObject('htmlfile'),
JSON;
htmlfile.write('<meta http-equiv="x-ua-compatible" content="IE=9" />');
htmlfile.close(JSON = htmlfile.parentWindow.JSON);
var obj = JSON.parse(stdin.ReadAll());
for (var i = obj.streams.length; i--;) {
if (obj.streams[i].height) WSH.Echo('height=' + obj.streams[i].height);
if (/hevc/i.test(obj.streams[i].codec_name)) WSH.Echo('hevc=true');
if (/aac/i.test(obj.streams[i].codec_name)) WSH.Echo('aac=true');
}
set "codec=" & set "sound="
for /f "tokens=*" %%i in ('ffprobe ... ') do (
for /f "tokens=3,4 delims=," %%a in (%%i) do (
if not defined codec (
set "codec=%%a"
set "hres=%%b"
) else (
if not defined sound set "sound=%%a"
)
)
)
echo %sound%,%codec%,%hres%
if there are blank lines before ffprobe
output, you should add the skip=n
keyword to for
loop.