vmarquet / ruby-mediainfo-simple

A Ruby wrapper for the MediaInfo command-line interface.
1 stars 1 forks source link

Doesn't work with MediaInfoLib - v17.12 #1

Open rgaufman opened 6 years ago

rgaufman commented 6 years ago

I'm using the latest version of the gem and MediaInfo v17.12. When using mediainfo directly, it works and identifies the multiple streams and that this is a video:

irb(main):014:0> puts `mediainfo './test.mp4'`
General
Complete name                            : ./test.mp4
Format                                   : MPEG-4
Format profile                           : Base Media
Codec ID                                 : isom (isom/iso2/avc1/mp41)
File size                                : 211 MiB
Duration                                 : 25 min 32 s
Overall bit rate mode                    : Variable
Overall bit rate                         : 1 152 kb/s
Writing application                      : Lavf53.21.1

Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : Main@L3.1
Format settings                          : CABAC / 3 Ref Frames
Format settings, CABAC                   : Yes
Format settings, ReFrames                : 3 frames
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
Duration                                 : 25 min 32 s
Bit rate                                 : 1 024 kb/s
Width                                    : 854 pixels
Height                                   : 480 pixels
Display aspect ratio                     : 16:9
Original display aspect ratio            : 16:9
Frame rate mode                          : Constant
Frame rate                               : 29.970 (30000/1001) FPS
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.083
Stream size                              : 187 MiB (89%)
Writing library                          : x264 core 123 r2189 35cf912
Encoding settings                        : cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x1:0x111 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=0 / b_adapt=1 / b_bias=0 / direct=1 / weightb=0 / open_gop=1 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=abr / mbtree=1 / bitrate=1024 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.25 / aq=1:1.00
Language                                 : English

Audio
ID                                       : 2
Format                                   : AAC
Format/Info                              : Advanced Audio Codec
Format profile                           : LC
Codec ID                                 : mp4a-40-2
Duration                                 : 25 min 32 s
Bit rate mode                            : Variable
Bit rate                                 : 124 kb/s
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Sampling rate                            : 48.0 kHz
Frame rate                               : 46.875 FPS (1024 SPF)
Compression mode                         : Lossy
Stream size                              : 22.7 MiB (11%)
Language                                 : English
Default                                  : Yes
Alternate group                          : 1

When using the gem, it does not identify the streams or that this is a video :(

irb(main):008:0> info = MediaInfo.new('./test.mp4')
=> #<MediaInfo:0x00007fc25b81fab8 @streams=[]>
irb(main):009:0> info.video?
=> false
irb(main):010:0> info.audio?
=> false

Any ideas?

rgaufman commented 6 years ago

Here is the XML data the latest version produces:

<?xml version="1.0" encoding="UTF-8"?>
<MediaInfo
    xmlns="https://mediaarea.net/mediainfo"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://mediaarea.net/mediainfo https://mediaarea.net/mediainfo/mediainfo_2_0.xsd"
    version="2.0">
<creatingLibrary version="17.12" url="https://mediaarea.net/MediaInfo">MediaInfoLib</creatingLibrary>
<media ref="test.mp4">
<track type="General">
<VideoCount>1</VideoCount>
<AudioCount>1</AudioCount>
<FileExtension>mp4</FileExtension>
<Format>MPEG-4</Format>
<Format_Profile>Base Media</Format_Profile>
<CodecID>isom</CodecID>
<FileSize>220743801</FileSize>
<Duration>1532.736</Duration>
<OverallBitRate_Mode>VBR</OverallBitRate_Mode>
<OverallBitRate>1152156</OverallBitRate>
<FrameRate>29.970</FrameRate>
<FrameCount>45934</FrameCount>
<StreamSize>1189500</StreamSize>
<HeaderSize>40</HeaderSize>
<DataSize>219554309</DataSize>
<FooterSize>1189452</FooterSize>
<IsStreamable>No</IsStreamable>
<File_Modified_Date>UTC 2018-03-11 23:23:32</File_Modified_Date>
<File_Modified_Date_Local>2018-03-11 23:23:32</File_Modified_Date_Local>
<Encoded_Application>Lavf53.21.1</Encoded_Application>
</track>

<track type="Video">
<StreamOrder>0</StreamOrder>
<ID>1</ID>
<Format>AVC</Format>
<Format_Profile>Main</Format_Profile>
<Format_Level>3.1</Format_Level>
<Format_Settings_CABAC>Yes</Format_Settings_CABAC>
<Format_Settings_RefFrames>3</Format_Settings_RefFrames>
<CodecID>avc1</CodecID>
<Duration>1532.665</Duration>
<BitRate>1024000</BitRate>
<Width>854</Width>
<Height>480</Height>
<Stored_Width>864</Stored_Width>
<Sampled_Width>854</Sampled_Width>
<Sampled_Height>480</Sampled_Height>
<PixelAspectRatio>0.999</PixelAspectRatio>
<DisplayAspectRatio>1.777</DisplayAspectRatio>
<DisplayAspectRatio_Original>1.778</DisplayAspectRatio_Original>
<Rotation>0.000</Rotation>
<FrameRate_Mode>CFR</FrameRate_Mode>
<FrameRate_Mode_Original>VFR</FrameRate_Mode_Original>
<FrameRate>29.970</FrameRate>
<FrameCount>45934</FrameCount>
<ColorSpace>YUV</ColorSpace>
<ChromaSubsampling>4:2:0</ChromaSubsampling>
<BitDepth>8</BitDepth>
<ScanType>Progressive</ScanType>
<StreamSize>195737109</StreamSize>
<Encoded_Library>x264 - core 123 r2189 35cf912</Encoded_Library>
<Encoded_Library_Name>x264</Encoded_Library_Name>
<Encoded_Library_Version>core 123 r2189 35cf912</Encoded_Library_Version>
<Encoded_Library_Settings>cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x1:0x111 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=0 / b_adapt=1 / b_bias=0 / direct=1 / weightb=0 / open_gop=1 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=abr / mbtree=1 / bitrate=1024 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.25 / aq=1:1.00</Encoded_Library_Settings>
<Language>en</Language>
</track>

<track type="Audio">
<StreamOrder>1</StreamOrder>
<ID>2</ID>
<Format>AAC</Format>
<Format_Profile>LC</Format_Profile>
<Format_Settings_SBR>No (Explicit)</Format_Settings_SBR>
<CodecID>mp4a-40-2</CodecID>
<Duration>1532.736</Duration>
<BitRate_Mode>VBR</BitRate_Mode>
<BitRate>124312</BitRate>
<Channels>2</Channels>
<ChannelPositions>Front: L R</ChannelPositions>
<ChannelLayout>L R</ChannelLayout>
<SamplesPerFrame>1024</SamplesPerFrame>
<SamplingRate>48000</SamplingRate>
<SamplingCount>73571328</SamplingCount>
<FrameRate>46.875</FrameRate>
<FrameCount>71847</FrameCount>
<Compression_Mode>Lossy</Compression_Mode>
<StreamSize>23817192</StreamSize>
<StreamSize_Proportion>0.10790</StreamSize_Proportion>
<Language>en</Language>
<Default>Yes</Default>
<AlternateGroup>1</AlternateGroup>
</track>

</media>
</MediaInfo>
rgaufman commented 6 years ago

A quick workaround to use in the meantime is:

irb(main):199:0> require 'active_support/all'
=> false
irb(main):200:0> Hash.from_xml(xml)
=> {"MediaInfo"=>{"xmlns"=>"https://mediaarea.net/mediainfo", "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation"=>"https://mediaarea.net/mediainfo https://mediaarea.net/mediainfo/mediainfo_2_0.xsd", "version"=>"2.0", "creatingLibrary"=>"MediaInfoLib", "media"=>{"ref"=>"test.mp4", "track"=>[{"type"=>"General", "VideoCount"=>"1", "AudioCount"=>"1", "FileExtension"=>"mp4", "Format"=>"MPEG-4", "Format_Profile"=>"Base Media", "CodecID"=>"isom", "FileSize"=>"220743801", "Duration"=>"1532.736", "OverallBitRate_Mode"=>"VBR", "OverallBitRate"=>"1152156", "FrameRate"=>"29.970", "FrameCount"=>"45934", "StreamSize"=>"1189500", "HeaderSize"=>"40", "DataSize"=>"219554309", "FooterSize"=>"1189452", "IsStreamable"=>"No", "File_Modified_Date"=>"UTC 2018-03-11 23:23:32", "File_Modified_Date_Local"=>"2018-03-11 23:23:32", "Encoded_Application"=>"Lavf53.21.1"}, {"type"=>"Video", "StreamOrder"=>"0", "ID"=>"1", "Format"=>"AVC", "Format_Profile"=>"Main", "Format_Level"=>"3.1", "Format_Settings_CABAC"=>"Yes", "Format_Settings_RefFrames"=>"3", "CodecID"=>"avc1", "Duration"=>"1532.665", "BitRate"=>"1024000", "Width"=>"854", "Height"=>"480", "Stored_Width"=>"864", "Sampled_Width"=>"854", "Sampled_Height"=>"480", "PixelAspectRatio"=>"0.999", "DisplayAspectRatio"=>"1.777", "DisplayAspectRatio_Original"=>"1.778", "Rotation"=>"0.000", "FrameRate_Mode"=>"CFR", "FrameRate_Mode_Original"=>"VFR", "FrameRate"=>"29.970", "FrameCount"=>"45934", "ColorSpace"=>"YUV", "ChromaSubsampling"=>"4:2:0", "BitDepth"=>"8", "ScanType"=>"Progressive", "StreamSize"=>"195737109", "Encoded_Library"=>"x264 - core 123 r2189 35cf912", "Encoded_Library_Name"=>"x264", "Encoded_Library_Version"=>"core 123 r2189 35cf912", "Encoded_Library_Settings"=>"cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x1:0x111 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=0 / b_adapt=1 / b_bias=0 / direct=1 / weightb=0 / open_gop=1 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=abr / mbtree=1 / bitrate=1024 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.25 / aq=1:1.00", "Language"=>"en"}, {"type"=>"Audio", "StreamOrder"=>"1", "ID"=>"2", "Format"=>"AAC", "Format_Profile"=>"LC", "Format_Settings_SBR"=>"No (Explicit)", "CodecID"=>"mp4a-40-2", "Duration"=>"1532.736", "BitRate_Mode"=>"VBR", "BitRate"=>"124312", "Channels"=>"2", "ChannelPositions"=>"Front: L R", "ChannelLayout"=>"L R", "SamplesPerFrame"=>"1024", "SamplingRate"=>"48000", "SamplingCount"=>"73571328", "FrameRate"=>"46.875", "FrameCount"=>"71847", "Compression_Mode"=>"Lossy", "StreamSize"=>"23817192", "StreamSize_Proportion"=>"0.10790", "Language"=>"en", "Default"=>"Yes", "AlternateGroup"=>"1"}]}}}
tracks = media_info['MediaInfo']['media']['track'].size
=> 3
irb(main):221:0> bitrate = media_info['MediaInfo']['media']['track'][1]['BitRate']
=> "1024000"
vmarquet commented 6 years ago

Hi! I've not used this for years, and I don't really have time to look into this now so you're on your own, sorry :(

But thanks for the report.

rgaufman commented 6 years ago

No worries, I came up with this which does everything I need :) <

require 'active_support/all'

class MediaInfo
  attr_reader :raw, :parsed

  def initialize(path)
    @path = path
    @raw = `mediainfo --Output=XML "#{path}"`
    @parsed = Hash.from_xml(@raw)
  end

  def streams
    @parsed.dig('MediaInfo', 'media', 'track')
  end

  def video_streams
    return unless streams?
    streams.select {|t| t.dig('type') == 'Video' }
  end

  def video
    return unless video_streams
    video_streams[0]
  end

  def hevc?
    return unless video
    video.dig('Format') == 'HEVC'
  end

  def audio_streams
    streams.select {|t| t.dig('type') == 'Audio' }
  end

  def audio
    return unless audio_streams
    audio_streams[0]
  end

  def streams?
    streams.class == Array
  end

  def video?
    return false unless streams?
    video_streams.count > 0
  end

  def audio?
    return false unless streams?
    audio_streams.count > 0
  end
end