Module: FastlaneCore::VideoUtils

Defined in:
fastlane_core/lib/fastlane_core/video_utils.rb

Class Method Summary collapse

Class Method Details

.read_video_duration_seconds(path) ⇒ Object

Pure Ruby MP4/QuickTime MOV container header parser reading mvhd to get duration in seconds. Note: Uses movie header (mvhd) time scale/duration, not per-track edit lists; adequate for gating. Input: path (String) to a local MP4/MOV file. Output: duration in seconds (Float), or nil on failure.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'fastlane_core/lib/fastlane_core/video_utils.rb', line 40

def self.read_video_duration_seconds(path)
  File.open(path, "rb") do |f|
    file_size = f.size
    while f.pos < file_size
      size, type = read_atom_header(f)
      break unless size && type
      return nil if size < 8
      content = size - 8
      if type == "moov"
        moov_end = f.pos + content
        duration = extract_duration_from_moov(f, moov_end)
        return duration if duration
      else
        skip(f, content)
      end
    end
  end
  nil
rescue => e
  FastlaneCore::UI.verbose("Failed to parse duration for '#{path}': #{e.class} - #{e.message}")
  nil
end

.read_video_resolution(path) ⇒ Object

Pure Ruby MP4/QuickTime MOV container header parser, reading tkhd to get width/height. Note: This reads container atoms/boxes only; it does NOT parse the video codec bitstream. Works regardless of codec as long as standard container headers exist. Input: path (String) to a local MP4/MOV file. Output: [width, height] (Array<Integer>) normalized to portrait (w <= h), or nil on failure.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'fastlane_core/lib/fastlane_core/video_utils.rb', line 13

def self.read_video_resolution(path)
  File.open(path, "rb") do |f|
    file_size = f.size
    while f.pos < file_size
      size, type = read_atom_header(f)
      break unless size && type
      return nil if size < 8
      content = size - 8
      if type == "moov"
        moov_end = f.pos + content
        resolution = extract_resolution_from_moov(f, moov_end)
        return resolution if resolution
      else
        skip(f, content)
      end
    end
  end
  nil
rescue => e
  FastlaneCore::UI.verbose("Failed to parse resolution for '#{path}': #{e.class} - #{e.message}")
  nil
end