3

I am totally unfamiliar with scripts in Windows, but are forced to use such a script. I would like someone to help me with the following problem. I want to process the output from ffmpeg command to save information about access an webcam to be used later. More precisely command is following:

ffmpeg -stats -hide_banner -list_devices true -f dshow -i dummy

and output is like this:

[dshow @ 02cec400] DirectShow video devices (some may be both video and audio devices)
[dshow @ 02cec400]  "Microsoft LifeCam Studio"
[dshow @ 02cec400]     Alternative name "@device_pnp_\\?\usb#vid_045e&pid_0772&mi_00#6&2a15e69b&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global"
[dshow @ 02cec400] DirectShow audio devices
[dshow @ 02cec400]  "Desktop Microphone (3- Studio -"
[dshow @ 02cec400]     Alternative name "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\Desktop Microphone (3- Studio -"
[dshow @ 02cec400]  "Line In (High Definition Audio "
[dshow @ 02cec400]     Alternative name "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\Line In (High Definition Audio "
[dshow @ 02cec400]  "Microphone (High Definition Aud"
[dshow @ 02cec400]     Alternative name "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\Microphone (High Definition Aud"

Typically, the first two occurence for ”Alternative name” from DirectShow correspond to video and audio, so for simplicity I want these two information saved in two variables. In this example is:

@device_pnp_\\?\usb#vid_045e&pid_0772&mi_00#6&2a15e69b&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global

and

@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\Desktop Microphone (3- Studio -

Can someone more experienced to help me with this task? Thanks in advance!

vlad2005
  • 81
  • 6

2 Answers2

4

This batch code assigns first device string to variable DeviceVideo and the second device string to variable DeviceAudio.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "DeviceVideo="

for /F "tokens=4,5*" %%I in ('ffmpeg.exe -stats -hide_banner -list_devices true -f dshow -i dummy 2^>^&1') do (
    if "%%I %%J" == "Alternative name" (
        if not defined DeviceVideo (
            set "DeviceVideo=%%~K"
        ) else (
            set "DeviceAudio=%%~K"
            goto DevicesOutput
        )
    )
)

:DevicesOutput
set Device
endlocal

ffmpeg outputs text messages to handle STDERR instead of STDOUT which is definitely not typical for console applications. Command FOR captures and processes just text printed to STDOUT.

For that reason it is necessary to redirect everything output by ffmpeg to handle STDERR to handle STDOUT using 2>&1 as Microsoft documented in article Using command redirection operators. It is necessary to escape with ^ the operators > and & because this redirection should be applied on execution of ffmpeg with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments and not on execution of command FOR by the command process which is processing the batch file.

Command FOR processes next the output lines of ffmpeg with skipping blank lines and also lines starting with a semicolon (default eol).

Each line is split up to strings using spaces/tabs as separators (default delims). It is specified with tokens=4,5* that only the strings 4, 5 and rest of the line after fifth spaces/tabs separated string are of interest and should be assigned to the loop variables I, J and K.

For example the line

[dshow @ 02cec400]     Alternative name "@device_pnp_\\?\usb#vid_045e&pid_0772&mi_00#6&2a15e69b&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global"

is split up to the strings

  1. [dshow ... ignored as token 1 is not specified.
  2. @ ... ignored as token 2 is not specified.
  3. 02cec400] ... ignored as token 3 is not specified.
  4. Alternative ... token 4 assigned to specified loop variable I.
  5. name ... token 5 assigned to loop variable J being the next character in ASCII table.
  6. "@device_pnp_\\?\usb#vid_045e&pid_0772&mi_00#6&2a15e69b&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global" ... token 6 specified with * matching rest of the line (with spaces and tabs) assigned to loop variable K being next but one character in ASCII table.

Inside the loop a case-sensitive string comparison is made to check if loop variable I and J, with a single space between, enclosed in double quotes is equal the string "Alternative name". The double quotes are not removed by IF before comparing the two strings.

A new device string is found in output on equal strings. In this case is checked next if the environment variable DeviceVideo explicitly undefined at top is still not defined which means the first device string is currently processed by the commands in body of FOR.

The device string is assigned without the surrounding double quotes because of %%~K instead of just %%K to either environment variable DeviceVideo on DeviceVideo not yet defined (first device string) or environment variable DeviceAudio (second device string).

As only the first two device strings are of interest, the loop is exited already after assigning the second device string to DeviceAudio.

All variables starting with the substring Device are output alphabetically sorted on next processed line which results for the example in the output:

DeviceAudio=@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\Desktop Microphone (3- Studio -
DeviceVideo=@device_pnp_\\?\usb#vid_045e&pid_0772&mi_00#6&2a15e69b&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global

Finally with command endlocal the current environment variables table with DeviceAudio and DeviceVideo is removed from memory, states of command extensions (enabled as by default enabled) and delayed expansion (disabled as by default disabled), and the current directory (not changed at all) are restored, and the initial environment variables table is made active again.

For even better understanding the used commands, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?
Mofi
  • 46,139
  • 17
  • 80
  • 143
3

You might try this (untestet!)

@echo off&setlocal disabledelayedexpansion
set "Alt1="
set "Alt2="
For /f tokens^=1^,2delims^=^" %%a in ('ffmpeg -stats -hide_banner -list_devices true -f dshow -i dummy 2^>^&1 ^| findstr /c:"Alternative name"') do (
   if not defined Alt1 (
      set "Alt1=%%~b"
   ) else (
      if not defined Alt2 (
         set "Alt2=%%~b" 
      )
   )
)
echo Alternative name 1: "%Alt1%"
echo Alternative name 2: "%Alt2%"
Endoro
  • 37,015
  • 8
  • 50
  • 63
  • Work like a charm!! Many thanks! Have an suggestion how to deal in batch script with registered trademark sign. Microsoft webcams have this sign in name and give me in command an strange symbol. I think is something related with font used by console. – vlad2005 Jul 03 '16 at 17:33
  • @vlad2005 This is a very difficult issue, it depends on your local settings, please read [here](http://stackoverflow.com/a/17177904/2098699). Please mark my answer as accepted, if so. Thanks. – Endoro Jul 03 '16 at 20:23