-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add preset to create simple thumbnails
- Loading branch information
1 parent
80b78aa
commit 201ad51
Showing
9 changed files
with
187 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative '../filters/scale' | ||
require_relative '../preset' | ||
|
||
module FFMPEG | ||
# rubocop:disable Style/Documentation | ||
module Presets | ||
# rubocop:enable Style/Documentation | ||
class << self | ||
def thumbnail( | ||
name: 'JPEG thumbnail', | ||
filename: '%<basename>s.thumb.jpg', | ||
metadata: nil, | ||
max_width: nil, | ||
max_height: nil | ||
) | ||
Thumbnail.new( | ||
name:, | ||
filename:, | ||
metadata:, | ||
max_width: max_width, | ||
max_height: max_height | ||
) | ||
end | ||
end | ||
|
||
# Preset to create a thumbnail from a video. | ||
class Thumbnail < Preset | ||
attr_reader :max_width, :max_height | ||
|
||
# @param name [String] The name of the preset. | ||
# @param filename [String] The filename format of the output. | ||
# @param metadata [Hash] The metadata to associate with the preset. | ||
# @param max_width [Numeric] The maximum width of the thumbnail. | ||
# @param max_height [Numeric] The maximum height of the thumbnail. | ||
# @yield The block to execute to compose the command arguments. | ||
def initialize(name: nil, filename: nil, metadata: nil, max_width: nil, max_height: nil, &) | ||
if max_width && !max_width.is_a?(Numeric) | ||
raise ArgumentError, "Unknown max_width format #{max_width.class}, expected #{Numeric}" | ||
end | ||
|
||
if max_height && !max_height.is_a?(Numeric) | ||
raise ArgumentError, "Unknown max_height format #{max_height.class}, expected #{Numeric}" | ||
end | ||
|
||
@max_width = max_width | ||
@max_height = max_height | ||
preset = self | ||
|
||
super(name:, filename:, metadata:) do | ||
arg 'ss', (media.duration / 2).floor if media.duration.is_a?(Numeric) | ||
arg 'frames:v', 1 | ||
filter preset.scale_filter(media) | ||
end | ||
end | ||
|
||
def scale_filter(media) | ||
return unless @max_width || @max_height | ||
|
||
Filters::Scale.contained(media, max_width: @max_width, max_height: @max_height) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,50 @@ module FFMPEG | |
|
||
module Filters | ||
describe Scale do | ||
describe '.contained' do | ||
let(:media) { Media.new(fixture_media_file('[email protected]')) } | ||
|
||
it 'raises ArgumentError if media is not an FFMPEG::Media' do | ||
expect { described_class.contained(nil) }.to raise_error(ArgumentError) | ||
expect { described_class.contained('media') }.to raise_error(ArgumentError) | ||
end | ||
|
||
it 'raises ArgumentError if max_width is not numeric' do | ||
expect { described_class.contained(media, max_width: 'foo') }.to raise_error(ArgumentError) | ||
end | ||
|
||
it 'raises ArgumentError if max_height is not numeric' do | ||
expect { described_class.contained(media, max_height: 'foo') }.to raise_error(ArgumentError) | ||
end | ||
|
||
it 'returns nil if max_width and max_height are not specified' do | ||
expect(described_class.contained(media)).to be_nil | ||
end | ||
|
||
it 'returns a contained scale filter' do | ||
expect(described_class.contained(media, max_width: 640).to_s).to eq('scale=w=640:h=-2') | ||
expect(described_class.contained(media, max_height: 480).to_s).to eq('scale=w=-2:h=480') | ||
expect(described_class.contained(media, max_width: 640, max_height: 480).to_s).to eq('scale=w=640:h=-2') | ||
end | ||
|
||
context 'when the media is rotated' do | ||
let(:media) { Media.new(fixture_media_file('[email protected]')) } | ||
|
||
it 'returns a contained scale filter' do | ||
expect(described_class.contained(media, max_width: 640).to_s).to eq('scale=w=-2:h=640') | ||
expect(described_class.contained(media, max_height: 480).to_s).to eq('scale=w=480:h=-2') | ||
expect(described_class.contained(media, max_width: 640, max_height: 480).to_s).to eq('scale=w=-2:h=640') | ||
end | ||
end | ||
|
||
context 'when the aspect ratio is higher than the max_width and max_height' do | ||
it 'returns a contained scale filter that scales to width' do | ||
expect(media).to receive(:calculated_aspect_ratio).and_return(2) | ||
expect(described_class.contained(media, max_width: 640, max_height: 480).to_s).to eq('scale=w=640:h=-2') | ||
end | ||
end | ||
end | ||
|
||
describe '#initialize' do | ||
it 'raises ArgumentError if width is not numeric or string' do | ||
expect { described_class.new(width: 1) }.not_to raise_error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters