Class: FFmpegCore::Probe
- Inherits:
-
Object
- Object
- FFmpegCore::Probe
- Defined in:
- lib/ffmpeg_core/probe.rb
Overview
Probe video metadata using ffprobe
Instance Attribute Summary collapse
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Instance Method Summary collapse
- #aspect_ratio ⇒ Object
- #audio_channel_layout ⇒ Object
- #audio_channels ⇒ Object
- #audio_codec ⇒ Object
- #audio_sample_rate ⇒ Object
-
#audio_stream ⇒ Object
Audio stream metadata.
- #audio_streams ⇒ Object
-
#bitrate ⇒ Object
Bitrate in kb/s.
- #chapters ⇒ Object
-
#duration ⇒ Object
Duration in seconds.
-
#exif ⇒ Object
EXIF metadata: merges format-level and video stream tags (FFmpeg 8.1+).
- #format_name ⇒ Object
- #frame_rate ⇒ Object
- #has_audio? ⇒ Boolean
- #has_video? ⇒ Boolean
- #height ⇒ Object
-
#initialize(path) ⇒ Probe
constructor
A new instance of Probe.
- #pixel_format ⇒ Object
- #resolution ⇒ Object
- #rotation ⇒ Object
- #subtitle_streams ⇒ Object
- #tags ⇒ Object
- #valid? ⇒ Boolean
- #video_codec ⇒ Object
- #video_level ⇒ Object
- #video_profile ⇒ Object
-
#video_stream ⇒ Object
Video stream metadata.
- #width ⇒ Object
Constructor Details
#initialize(path) ⇒ Probe
Returns a new instance of Probe.
11 12 13 14 15 16 |
# File 'lib/ffmpeg_core/probe.rb', line 11 def initialize(path) @path = path.to_s @metadata = nil validate_file! probe! end |
Instance Attribute Details
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
9 10 11 |
# File 'lib/ffmpeg_core/probe.rb', line 9 def @metadata end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
9 10 11 |
# File 'lib/ffmpeg_core/probe.rb', line 9 def path @path end |
Instance Method Details
#aspect_ratio ⇒ Object
106 107 108 |
# File 'lib/ffmpeg_core/probe.rb', line 106 def aspect_ratio video_stream&.dig("display_aspect_ratio") end |
#audio_channel_layout ⇒ Object
138 139 140 |
# File 'lib/ffmpeg_core/probe.rb', line 138 def audio_channel_layout audio_stream&.dig("channel_layout") end |
#audio_channels ⇒ Object
134 135 136 |
# File 'lib/ffmpeg_core/probe.rb', line 134 def audio_channels audio_stream&.dig("channels") end |
#audio_codec ⇒ Object
50 51 52 |
# File 'lib/ffmpeg_core/probe.rb', line 50 def audio_codec audio_stream&.dig("codec_name") end |
#audio_sample_rate ⇒ Object
130 131 132 |
# File 'lib/ffmpeg_core/probe.rb', line 130 def audio_sample_rate audio_stream&.dig("sample_rate")&.to_i end |
#audio_stream ⇒ Object
Audio stream metadata
34 35 36 |
# File 'lib/ffmpeg_core/probe.rb', line 34 def audio_stream @audio_stream ||= streams.find { |s| s["codec_type"] == "audio" } end |
#audio_streams ⇒ Object
110 111 112 |
# File 'lib/ffmpeg_core/probe.rb', line 110 def audio_streams streams.select { |s| s["codec_type"] == "audio" } end |
#bitrate ⇒ Object
Bitrate in kb/s
24 25 26 |
# File 'lib/ffmpeg_core/probe.rb', line 24 def bitrate @metadata.dig("format", "bit_rate")&.to_i&./(1000) end |
#chapters ⇒ Object
118 119 120 |
# File 'lib/ffmpeg_core/probe.rb', line 118 def chapters @metadata.fetch("chapters", []) end |
#duration ⇒ Object
Duration in seconds
19 20 21 |
# File 'lib/ffmpeg_core/probe.rb', line 19 def duration @metadata.dig("format", "duration")&.to_f end |
#exif ⇒ Object
EXIF metadata: merges format-level and video stream tags (FFmpeg 8.1+)
155 156 157 158 159 |
# File 'lib/ffmpeg_core/probe.rb', line 155 def exif = @metadata.dig("format", "tags") || {} = video_stream&.dig("tags") || {} .merge() end |
#format_name ⇒ Object
122 123 124 |
# File 'lib/ffmpeg_core/probe.rb', line 122 def format_name @metadata.dig("format", "format_name") end |
#frame_rate ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ffmpeg_core/probe.rb', line 70 def frame_rate return nil unless video_stream # Parse frame rate (e.g., "30000/1001" or "30") r_frame_rate = video_stream["r_frame_rate"] return nil unless r_frame_rate if r_frame_rate.include?("/") num, den = r_frame_rate.split("/").map(&:to_f) num / den else r_frame_rate.to_f end end |
#has_audio? ⇒ Boolean
150 151 152 |
# File 'lib/ffmpeg_core/probe.rb', line 150 def has_audio? !audio_stream.nil? end |
#has_video? ⇒ Boolean
146 147 148 |
# File 'lib/ffmpeg_core/probe.rb', line 146 def has_video? !video_stream.nil? end |
#height ⇒ Object
62 63 64 65 66 67 68 |
# File 'lib/ffmpeg_core/probe.rb', line 62 def height val = video_stream&.dig("height") return val unless val return val if (rotation || 0) % 180 == 0 video_stream&.dig("width") end |
#pixel_format ⇒ Object
142 143 144 |
# File 'lib/ffmpeg_core/probe.rb', line 142 def pixel_format video_stream&.dig("pix_fmt") end |
#resolution ⇒ Object
85 86 87 88 89 |
# File 'lib/ffmpeg_core/probe.rb', line 85 def resolution return nil unless width && height "#{width}x#{height}" end |
#rotation ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/ffmpeg_core/probe.rb', line 91 def rotation return nil unless video_stream # Try to find rotation in tags (common in MP4/MOV) = video_stream.fetch("tags", {}) return ["rotate"].to_i if ["rotate"] # Try side_data_list (common in some newer formats) side_data = video_stream.fetch("side_data_list", []).find { |sd| sd.key?("rotation") } return side_data["rotation"].to_i if side_data # Default to 0 if not found 0 end |
#subtitle_streams ⇒ Object
114 115 116 |
# File 'lib/ffmpeg_core/probe.rb', line 114 def subtitle_streams streams.select { |s| s["codec_type"] == "subtitle" } end |
#tags ⇒ Object
126 127 128 |
# File 'lib/ffmpeg_core/probe.rb', line 126 def @metadata.dig("format", "tags") || {} end |
#valid? ⇒ Boolean
161 162 163 |
# File 'lib/ffmpeg_core/probe.rb', line 161 def valid? !video_stream.nil? end |
#video_codec ⇒ Object
38 39 40 |
# File 'lib/ffmpeg_core/probe.rb', line 38 def video_codec video_stream&.dig("codec_name") end |
#video_level ⇒ Object
46 47 48 |
# File 'lib/ffmpeg_core/probe.rb', line 46 def video_level video_stream&.dig("level") end |
#video_profile ⇒ Object
42 43 44 |
# File 'lib/ffmpeg_core/probe.rb', line 42 def video_profile video_stream&.dig("profile") end |
#video_stream ⇒ Object
Video stream metadata
29 30 31 |
# File 'lib/ffmpeg_core/probe.rb', line 29 def video_stream @video_stream ||= streams.find { |s| s["codec_type"] == "video" } end |
#width ⇒ Object
54 55 56 57 58 59 60 |
# File 'lib/ffmpeg_core/probe.rb', line 54 def width val = video_stream&.dig("width") return val unless val return val if (rotation || 0) % 180 == 0 video_stream&.dig("height") end |