media file: fix calculation of video/animation duration.

Fix how the duration of videos and animated GIFs / PNGs is calculated.
If we can't determine the duration from the file metadata, then play the
entire video or animation back using FFmpeg and scrape the duration and
frame count.

This is necessary for things like WebM files where the duration metadata
is optional, or animated GIFs and PNGs that don't have a duration field
in the metadata, only a frame count and a sequence of frame delays.
This commit is contained in:
evazion
2021-10-17 20:15:51 -05:00
parent d8de58d991
commit 8b3ab04724
3 changed files with 47 additions and 52 deletions

View File

@@ -188,7 +188,7 @@ class MediaFileTest < ActiveSupport::TestCase
should "determine the duration of the video" do
file = MediaFile.open("test/files/test-audio.mp4")
assert_equal(1.002667, file.duration)
assert_equal(10, file.frame_rate)
assert_equal(10/1.002667, file.frame_rate)
assert_equal(10, file.frame_count)
file = MediaFile.open("test/files/test-300x300.mp4")
@@ -202,8 +202,8 @@ class MediaFileTest < ActiveSupport::TestCase
should "determine the duration of the video" do
file = MediaFile.open("test/files/test-512x512.webm")
assert_equal(0.48, file.duration)
assert_equal(50, file.frame_rate)
assert_equal(24, file.frame_count)
assert_equal(10/0.48, file.frame_rate)
assert_equal(10, file.frame_count)
end
end
@@ -245,8 +245,8 @@ class MediaFileTest < ActiveSupport::TestCase
assert_equal(false, file.is_corrupt?)
assert_equal(true, file.is_animated?)
assert_equal(9, file.duration)
assert_equal(0.33, file.frame_rate.round(2))
assert_equal(3.0, file.duration)
assert_equal(1.0, file.frame_rate)
assert_equal(3, file.frame_count)
end
end
@@ -264,14 +264,14 @@ class MediaFileTest < ActiveSupport::TestCase
end
context "that is animated but with an unspecified frame rate" do
should "have an assumed frame rate of 10FPS" do
should "have an assumed frame rate of ~6.66 FPS" do
file = MediaFile.open("test/files/test-animated-inf-fps.png")
assert_equal(false, file.is_corrupt?)
assert_equal(true, file.is_animated?)
assert_equal(0.2, file.duration)
assert_equal(0.3, file.duration)
assert_equal(2, file.frame_count)
assert_equal(10, file.frame_rate)
assert_equal(2/0.3, file.frame_rate)
end
end