Fall back to video container for duration

Some video formats, such as WebM, do not store duration information at
the level of the video stream.  Instead, the duration is stored as part
of the container format information.

This commit modifies `VideoAnalyzer` to use the duration from the video
container when the duration from the video stream is not available.

Fixes #40130.
This commit is contained in:
Jonathan Hefner 2020-08-31 07:48:06 -05:00 committed by GitHub
parent 57da1d0188
commit a197d39e13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 4 deletions

View File

@ -44,7 +44,8 @@ module ActiveStorage
end
def duration
Float(video_stream["duration"]) if video_stream["duration"]
duration = video_stream["duration"] || container["duration"]
Float(duration) if duration
end
def angle
@ -98,12 +99,22 @@ module ActiveStorage
probe["streams"] || []
end
def container
probe["format"] || {}
end
def probe
download_blob_to_tempfile { |file| probe_from(file) }
@probe ||= download_blob_to_tempfile { |file| probe_from(file) }
end
def probe_from(file)
IO.popen([ ffprobe_path, "-print_format", "json", "-show_streams", "-v", "error", file.path ]) do |output|
IO.popen([ ffprobe_path,
"-print_format", "json",
"-show_streams",
"-show_format",
"-v", "error",
file.path
]) do |output|
JSON.parse(output.read)
end
rescue Errno::ENOENT

View File

@ -45,9 +45,21 @@ class ActiveStorage::Analyzer::VideoAnalyzerTest < ActiveSupport::TestCase
assert_nil metadata[:display_aspect_ratio]
end
test "analyzing a video with a container-specified duration" do
blob = create_file_blob(filename: "video.webm", content_type: "video/webm")
metadata = extract_metadata_from(blob)
assert_equal 640, metadata[:width]
assert_equal 480, metadata[:height]
assert_equal 5.229000, metadata[:duration]
end
test "analyzing a video without a video stream" do
blob = create_file_blob(filename: "video_without_video_stream.mp4", content_type: "video/mp4")
metadata = extract_metadata_from(blob)
assert_equal({ "analyzed" => true, "identified" => true }, metadata)
assert_not_includes metadata, :width
assert_not_includes metadata, :height
assert_equal 1.022000, metadata[:duration]
end
end

Binary file not shown.