arrays - MediaInfo CLI vbs 多个音频和文本流问题
问题描述
我想从电影文件中输出选定的参数。我这样做是这样的:
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
对于常规和视频流,这些命令(示例):
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"
正在生成两行或多行(取决于电影文件包含多少流),如下所示:
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
我认为有必要将音频和文本流的“多行”结果插入到一些动态数组中,并在下一步中通过它们并将“排序”值插入到输出文件中,或者第二个选项是对最终输出文件进行排序但是在这两种情况下,但我不知道该怎么做。
解决方案
这是可用于收集选定属性的 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
但这是外观问题。
推荐阅读
- javascript - Puppeteer:如何使用 document.evaluate 评估 xpath?
- android - Firebase 身份验证 - 使用现有的 WP 网站凭据登录?
- shopware - 插件已加载,但下拉列表中的类别未加载
- python - 并发队列的循环垃圾收集(Python C 扩展)
- matlab - xarr 和 yarr 必须采用什么形式才能返回满足方程的所有坐标
- next.js - Nextjs - multer - TypeError:无法读取未定义的属性“传输编码”
- html - 如何向 Material-UI Button 添加数据属性?
- sas - 如何将子组与SAS中的整个组进行比较?
- r - R循环没有循环正确的次数
- reactjs - 为 react-hook-form 中的复选框设置 initialValues 存在问题。在输入中,下拉菜单效果很好。为什么?