Skip to content

Commit 4c6c19d

Browse files
bajankristofclaude
andcommitted
fix: detect more common file extensions correctly
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent afaf5a4 commit 4c6c19d

3 files changed

Lines changed: 76 additions & 5 deletions

File tree

lib/ffmpeg/media.rb

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,26 +78,50 @@ def initialize(message, output)
7878
when /\Adash\b/ then '.mpd'
7979
when /\bhls\b/ then '.m3u8'
8080
when /\bmpegts(raw)?\b/ then '.ts'
81-
when /\bmpegvideo\b/ then '.mpg'
82-
when /\blive_flv\b/ then '.flv'
83-
when /\basf_o\b/ then '.asf'
81+
when /\bmpeg(video\b|\z)/ then '.mpg'
82+
when /\blive_flv\b/ then '.flv'
83+
when /\basf\b/
84+
if video?
85+
'.wmv'
86+
elsif audio?
87+
'.wma'
88+
else
89+
'.asf'
90+
end
8491
when /\b(mov|mp4)\b/
8592
case major_brand
8693
when nil, /\Aqt\b/i then '.mov'
8794
when /\Am4a\b/i then '.m4a'
8895
when /\Am4v\b/i then '.m4v'
8996
when /\Am4s\b/i then '.m4s'
90-
else '.mp4'
97+
when /\A3g2/i then '.3g2'
98+
when /\A3gp/i then '.3gp'
99+
when /\Af4v\b/i then '.f4v'
100+
when /\Af4p\b/i then '.f4p'
101+
when /\Af4a\b/i then '.f4a'
102+
when /\Af4b\b/i then '.f4b'
103+
when /\Aavi[fs]\b/i then '.avif'
104+
else '.mp4'
91105
end
92106
when /\bmatroska\b/
93107
if streams
94-
.select { _1.video? || _1.audio? }
108+
.select(&:av?)
95109
.reject(&:attached_pic?)
96110
.all? { WEBM_CODEC_NAMES.include?(_1.codec_name) }
97111
'.webm'
98112
else
99113
'.mkv'
100114
end
115+
when /\bogg\b/
116+
if video_streams?
117+
'.ogv'
118+
elsif include_codec_name?('opus')
119+
'.opus'
120+
elsif include_codec_name?('speex')
121+
'.spx'
122+
else
123+
'.ogg'
124+
end
101125
else
102126
muxer =
103127
format_name
@@ -238,6 +262,20 @@ def local?
238262
@valid
239263
end
240264

265+
# Whether the media contains any of the specified codec names.
266+
#
267+
# @return [Boolean]
268+
autoload def include_codec_name?(*codec_names)
269+
self.codec_names.any? { codec_names.include?(_1) }
270+
end
271+
272+
# Returns the set of all codec names used in the media's streams.
273+
#
274+
# @return [Set<String>]
275+
autoload def codec_names
276+
@codec_names ||= streams.map(&:codec_name).compact.to_set
277+
end
278+
241279
# Returns the major brand of the media (if any).
242280
autoload def major_brand
243281
tags&.fetch(:major_brand, nil)&.to_s&.strip

lib/ffmpeg/stream.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,13 @@ def audio?
115115
codec_type == :audio
116116
end
117117

118+
# Whether the stream is an audio or video stream.
119+
#
120+
# @return [Boolean]
121+
def av?
122+
video? || audio?
123+
end
124+
118125
# Whether the stream is marked as default.
119126
#
120127
# @return [Boolean]

spec/ffmpeg/stream_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,32 @@ module FFMPEG
6262
end
6363
end
6464

65+
describe '#av?' do
66+
context 'when the codec type is video' do
67+
let(:metadata) { { codec_type: 'video' } }
68+
69+
it 'returns true' do
70+
expect(subject.av?).to be(true)
71+
end
72+
end
73+
74+
context 'when the codec type is audio' do
75+
let(:metadata) { { codec_type: 'audio' } }
76+
77+
it 'returns true' do
78+
expect(subject.av?).to be(true)
79+
end
80+
end
81+
82+
context 'when the codec type is not video or audio' do
83+
let(:metadata) { { codec_type: 'subtitle' } }
84+
85+
it 'returns false' do
86+
expect(subject.av?).to be(false)
87+
end
88+
end
89+
end
90+
6591
describe '#default?' do
6692
context 'when marked as default' do
6793
let(:metadata) { { disposition: { default: 1 } } }

0 commit comments

Comments
 (0)