MediaInfo CLI vbs несколько аудио и текстовых потоков проблема - PullRequest
1 голос
/ 02 мая 2020

Я хочу вывести выбранные параметры из файлов mov ie. Я делаю это следующим образом:

arrGeneral = Array("General;Video Format List: %Video_Format_List%","General;File name: %FileNameExtension%","General;Commercial name: %Format_Commercial%")
arrVideo = Array("Video;ID: %ID%","Video;Format: %Format/String%","Video;Format info: %Format/Info%","Video;Format profile: %Format_Profile%","Video;Bit rate: %BitRate/String%")
arrAudio = Array("Audio;ID: %ID%\n","Audio;Format: %Format%\n","Audio;Format info: %Format/Info%\n","Audio;Commercial name: %Format_Commercial%\n","Audio;Codec ID: %CodecID%\n")
arrText = Array("Text;ID: %ID%\n","Text;Format: %Format/String%\n","Text;Codec ID: %CodecID/Info%\n","Text;Title: %Title%\n","Text;Language: %Language/String%\n")

' == General section ==
 objFileToWrite.Write "General" & vbCrLf
 for i = 0 to UBound(arrGeneral)
  commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrGeneral(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
  result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
  objFileToWrite.Write result 
 next
 objFileToWrite.Write "----------" & vbCrLf

' == Video section ==
objFileToWrite.Write "Video" & vbCrLf
 for i = 0 to UBound(arrVideo) 
  commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrVideo(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
  result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
  objFileToWrite.Write result
 next
objFileToWrite.Write "----------" & vbCrLf

' == Audio section ==
' Here is a problem beacuse it might be more than 1 Audio stream
objFileToWrite.Write "Audio" & vbCrLf
 for i = 0 to UBound(arrAudio) 
  commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrAudio(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
  result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
  objFileToWrite.Write result
 next
objFileToWrite.Write "----------" & vbCrLf

Для потоков General и Video эти команды (примеры):

MediaInfo.exe --Output="General;Video Format List: %Video_Format_List%" "Sample.mkv"
MediaInfo.exe --Output="Video;Format info: %Format/Info%" "Sample.mkv"

генерируют однострочные результаты, например:

Video Format List: HEVC
Format info: High Efficiency Video Coding

поэтому мой скрипт правильно создает выходной файл, который содержит:

General
Video Format List: HEVC
File name: Sample.mkv
Commercial name: Matroska
Format version: Version 4
File size: 10.03 GiB
Duration: 1 h 52 min 15 s 744 ms
Overall bit rate: 12.8 Mb/s
----------
Video
ID: 1
Format: HEVC
Format info: High Efficiency Video Coding
Format profile: Main 10@L4@Main
Bit rate: 8 525 kb/s
Width: 1 920 pixels
Height: 1 080 pixels
Display aspect ratio: 1.778
Display aspect ratio: 16:9
Frame rate mode: Constant
Frame rate: 23.976 (24000/1001) FPS
Color space: YUV
Chroma subsampling: 4:2:0
Bit depth: 10 bits
Video stream size: 6.68 GiB (67%)
----------

Но для аудио и текста (субтитров) может быть несколько потоков и одна команда:

MediaInfo.exe --Output="Audio;Format info: %Format/Info%\n" "Sample.mkv"

генерирует две или более строки (зависит от того, сколько потоков содержит файл mov ie), например:

Format info: Digital Theater Systems
Format info: Audio Coding 3

В результате в выходном файле я получаю что-то вроде этого :

Audio
ID: 2
ID: 3

Format: DTS
Format: AC-3

Format info: Digital Theater Systems
Format info: Audio Coding 3

Commercial name: DTS-HD Master Audio
Commercial name: Dolby Digital

Codec ID: A_DTS
Codec ID: A_AC3

Bit rate: 3 958 kb/s
Bit rate: 192 kb/s

но ожидаемый результат:

Audio #2
ID: 2
Format: DTS
Format info: Digital Theater Systems
Commercial name: DTS-HD Master Audio
Codec ID: A_DTS
Bit rate: 3 958 kb/s

Audio #3
ID: 3
Format: AC-3
Format info: Audio Coding 3
Commercial name: Dolby Digital
Codec ID: A_AC3
Bit rate: 192 kb/s

Я думаю, что было бы необходимо вставить "многострочные" результаты потоков аудио и текста в некоторые массивы c и следующий шаг к go через них и вставке в выходной файл «отсортированных» значений или второй вариант - сортировка окончательного выходного файла, но в обоих случаях, но я понятия не имею, как это сделать.

1 Ответ

1 голос
/ 03 мая 2020

Вот скрипт vbs, который можно использовать для сбора выбранных атрибутов:

InVideoFile = "C:\Temp\Sample.mkv"
InVideoFile = replace(InVideoFile,chr(34),"")
inFile = Left(InVideoFile, Len(InVideoFile) -4) & "-All.txt"
outFile = Left(inFile, Len(inFile) -4) & "-MediaInfo.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")

if objFSO.FileExists(inFile) then
 objFSO.DeleteFile inFile
end if
' MediaInfo.exe location below in ProgramToExecute variable
' MediaInfo.exe (Interface CLI) download location: https://mediaarea.net/en/MediaInfo/Download/Windows
ProgramToExecute = "C:\Program Files\MediaInfo\MediaInfo_CLI\MediaInfo.exe"
commandToRun = "cmd /C " & chr(34) & chr(34) & ProgramToExecute & chr(34) & " -f " & chr(34) & InVideoFile &chr(34) & " > " &chr(34) & inFile &chr(34) & chr(34)
Dim objShell
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run commandToRun,1,true
Set objShell = Nothing

Set objFileToRead = objFSO.OpenTextFile(inFile, 1)
Set objFileToWrite = objFSO.CreateTextFile(outFile,True)

Dim arrGeneral
Dim arrVideo
Dim arrAudio
Dim arrText

' Attributes that are need to be collected are taken from the result of command MediaInfo.exe --Info-Parameters
' Arrays elements are build in the following way:
' section;Text %Attribute%Delimiter
' examples:
' "General;Video Format List: %Video_Format_List%"
' "Video;Format profile: %Format_Profile%"
' "Audio;Channel(s): %Channel(s)/String%|"
' "Text;Format: %Format/String%|"
' Audio and Text sections  might contain more than one stream. Result is delimited by "|" character (can be used another) and later on is split
arrGeneral = Array("General;Video Format List: %Video_Format_List%","General;File name: %FileNameExtension%","General;Commercial name: %Format_Commercial%","General;Format version: %Format_Version%","General;File size: %FileSize/String4%","General;Duration: %Duration/String1%","General;Overall bit rate: %OverallBitRate/String%")
arrVideo = Array("Video;ID: %ID%","Video;Format: %Format/String%","Video;Format info: %Format/Info%","Video;Format profile: %Format_Profile%","Video;Bit rate: %BitRate/String%","Video;Width: %Width/String%","Video;Height: %Height/String%","Video;Display aspect ratio: %DisplayAspectRatio/String%","Video;Frame rate mode: %FrameRate_Mode/String%","Video;Frame rate: %FrameRate/String%","Video;Color space: %ColorSpace%","Video;Chroma subsampling: %ChromaSubsampling/String%","Video;Bit depth: %BitDepth/String%","Video;Video stream size: %StreamSize/String5%","Video;Colour primaries: %colour_primaries%","Video;Transfer characteristices: %transfer_characteristics%","Video;Matrix coefficients: %matrix_coefficients%")
arrAudio = Array("Audio;ID: %ID%|","Audio;Format: %Format%|","Audio;Format info: %Format/Info%|","Audio;Commercial name: %Format_Commercial%|","Audio;Codec ID: %CodecID%|","Audio;Bit rate: %BitRate/String%|","Audio;Channel(s): %Channel(s)/String%|","Audio;Channel positions: %ChannelPositions%|","Audio;Channel layout: %ChannelLayout%|","Audio;Sampling rate: %SamplingRate/String%|","Audio;Bit depth: %BitDepth/String%|","Audio;Compression mode: %Compression_Mode/String%|","Audio;Audio stream size: %StreamSize/String5%|","Audio;Title: %Title%|","Audio;Language: %Language/String%|","Audio;Default: %Default/String%|","Audio;Forced: %Forced/String%|")
arrText = Array("Text;ID: %ID%|","Text;Format: %Format/String%|","Text;Codec ID: %CodecID/Info%|","Text;Title: %Title%|","Text;Language: %Language/String%|","Text;Default: %Default/String%|","Text;Forced: %Forced/String%|")

' == General section ==
 objFileToWrite.Write "General" & vbCrLf
 for i = 0 to UBound(arrGeneral)
  commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrGeneral(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
  result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
  resultNoCRLF = Replace(result, vbCRLF, "")
    if right(resultNoCRLF,2) <> ": " then
     objFileToWrite.Write result
    end if 
 next
 objFileToWrite.Write "----------" & vbCrLf

' == Video section ==
objFileToWrite.Write "Video" & vbCrLf
 for i = 0 to UBound(arrVideo) 
  commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrVideo(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
  result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
  resultNoCRLF = Replace(result, vbCRLF, "")
    if right(resultNoCRLF,2) <> ": " then
     objFileToWrite.Write result
    end if 
 next
objFileToWrite.Write "----------" & vbCrLf

' == Audio section ==
' It might be more than 1 Audio stream
objFileToWrite.Write "Audio" & vbCrLf
 for i = 0 to UBound(arrAudio) 
  commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrAudio(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
  result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
  Dim arrAudioSplit
  arrAudioSplit = Split(result,"|")
  ReDim Preserve arrA(UBound(arrAudio),UBound(arrAudioSplit)-1)
   for z = 0 to UBound(arrAudioSplit)-1
    arrA(i,z) =  arrAudioSplit(z)
   next 
 next
  for j = 0 to Ubound(arrAudioSplit) - 1
   for k = 0 to Ubound(arrAudio)
      if right(arrA(k,j),2) <> ": " then
       objFileToWrite.Write arrA(k,j) & vbCrLf
      end if
   next
  objFileToWrite.Write "----------" & vbCrLf
  next   

' == Text (subtitles) section ==
' It might be more than 1 Text stream
objFileToWrite.Write "Text" & vbCrLf
 for i = 0 to UBound(arrText) 
  commandToRun = chr(34) & ProgramToExecute & chr(34) & " --Output=" & chr(34) & arrText(i) & chr(34) & " " & chr(34) & InVideoFile & chr(34)
  result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll
  Dim arrTextSplit
  arrTextSplit = Split(result,"|")
  ReDim Preserve arrT(UBound(arrText),UBound(arrTextSplit)-1)
   for z = 0 to UBound(arrTextSplit)-1
    arrT(i,z) =  arrTextSplit(z)
   next 
 next
  for j = 0 to Ubound(arrTextSplit) - 1
   for k = 0 to Ubound(arrText)
     if right(arrT(k,j),2) <> ": " then
      objFileToWrite.Write arrT(k,j) & vbCrLf
     end if 
   next
  objFileToWrite.Write "----------" & vbCrLf
  next   

' == Menu (Chapters) section ==
' Have to be handled in different way by checking result of the command MediaInfo.exe -f inputfile
 Set objFileToRead = objFSO.OpenTextFile(inFile, 1)
 startReadingMenu = false
 menuNextLine = 1
 do while not objFileToRead.AtEndOfStream
  strLineOriginal = Trim(objFileToRead.ReadLine())
  MenuNextLine = MenuNextLine + 1
  if Left(strLineOriginal,16) = "Chapters_Pos_End" then
   startReadingMenu = true
   MenuNextLine = 0
  end if 
  if startReadingMenu then
   objFileToWrite.Write "Chapters" & vbCrLf
   startReadingMenu = false
  end if  
  if MenuNextLine = 1 then
   objFileToWrite.Write strLineOriginal & vbCrLf
   MenuNextLine = 0
  end if 
 loop

' Close files
 objFileToRead.Close
 Set objFileToRead = Nothing
 objFileToWrite.Close
 Set objFileToWrite = Nothing

' Dislay result file in notepad
 DisplayInNotepad = "notepad.exe " & chr(34) & outFile &chr(34)
 commandToRun = "cmd /C " & DisplayInNotepad
 Dim objSh
 Set objSh = WScript.CreateObject("WScript.Shell")
 objSh.Run commandToRun,0,true
 Set objSh = Nothing

' Cleanup
 if objFSO.FileExists(inFile) then
  objFSO.DeleteFile inFile
 end if
 if objFSO.FileExists(outFile) then
  objFSO.DeleteFile outFile
 end if

Единственный оставшийся вопрос - как скрыть окно cmd, которое мигает при вызове строки:

result = CreateObject("WScript.Shell").Exec(commandToRun).StdOut.ReadAll

но это вопрос косметики c.

...