video-gif-previewer 0.0.3 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/gif_previewer.rb +89 -9
- data/lib/video-gif-previewer/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '08e35907ca5d95b4ce59a135cbe9572a1f13240df1c8abdfed340f3ada0fcb28'
|
4
|
+
data.tar.gz: 34bc9c5bda01697d00d0d45d7679bf05fd1e26769e8cf4384c0b8d06a2e2342d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9427e2a3edad7c1140e8d00b85c8205cde639167a5316748e2d32a9d10a89a5511ceeae8cabcbe6641833bc2eb08b089aa8ae7e842273111f4896a33089c018d
|
7
|
+
data.tar.gz: deafe286cb4ff483b60287fd9898eed29cefff1659b64df98abfc262cf01d894c0fc58fb38c1154290b7d23094d0ebaaff3e8737438c4bf0259a629c7a1752fc
|
data/lib/gif_previewer.rb
CHANGED
@@ -1,24 +1,104 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'timeout'
|
4
|
+
|
3
5
|
class GifPreviewer < ActiveStorage::Previewer::VideoPreviewer
|
6
|
+
MAX_PROCESSING_TIME = 60
|
7
|
+
|
4
8
|
def preview(**options)
|
9
|
+
Rails.logger.info(msg: 'Downloading Blob', blob: @blob)
|
5
10
|
download_blob_to_tempfile do |input|
|
6
|
-
|
11
|
+
file_duration = duration(input_file: input)
|
12
|
+
Rails.logger.info(msg: 'generation of gif preview starting', blob: @blob)
|
13
|
+
draw_relevant_frames_from input, file_duration do |output|
|
14
|
+
Rails.logger.info(msg: 'generation of gif preview completed')
|
7
15
|
yield io: output, filename: "#{blob.filename.base}-preview.gif", content_type: "image/gif", **options
|
8
16
|
end
|
9
17
|
end
|
18
|
+
|
19
|
+
rescue Timeout::Error
|
20
|
+
Rails.logger.error(msg: "Timeout::Error, processing took too long", max_allowed_time: MAX_PROCESSING_TIME)
|
21
|
+
|
22
|
+
# If we take too long encoding a gif, fallback to the standard rails VideoPreviewer
|
23
|
+
super
|
24
|
+
rescue ActiveStorage::PreviewError => e
|
25
|
+
Rails.logger.error(msg: "ActiveStorage::PreviewError", message: e.message)
|
26
|
+
|
27
|
+
# If we hit an issue encoding a gif, fallback to the standard rails VideoPreviewer
|
28
|
+
super
|
10
29
|
end
|
11
30
|
|
12
31
|
private
|
13
32
|
|
33
|
+
def ffprobe_path
|
34
|
+
ActiveStorage.paths[:ffprobe] || "ffprobe"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Use ffprobe to analyze the media for duration
|
38
|
+
def duration(input_file: nil)
|
39
|
+
start_time = Time.now
|
40
|
+
|
41
|
+
file_duration = if input_file.present?
|
42
|
+
duration_command(input_file)
|
43
|
+
else
|
44
|
+
download_blob_to_tempfile do |file|
|
45
|
+
duration_command(file)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Rails.logger.info(msg: 'ffprobe for durations finished', file_duration:, elapsed_time: Time.now - start_time)
|
50
|
+
|
51
|
+
file_duration
|
52
|
+
end
|
53
|
+
|
54
|
+
def duration_command(input_file)
|
55
|
+
`#{ffprobe_path} -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 #{input_file.path}`.to_f.floor.to_i
|
56
|
+
end
|
57
|
+
|
58
|
+
# Use file_duration to either pick a random place ~33% into the file, or if the file is too short, use 0
|
59
|
+
def start_frame(file_duration:)
|
60
|
+
if file_duration > 10
|
61
|
+
mid_frame = (file_duration.to_f / 3).floor
|
62
|
+
mid_frame > 3 ? mid_frame : 3
|
63
|
+
else
|
64
|
+
0
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Use file_duration to pick an end frame frame_duration after the start, or if the file is too short, use file_duration
|
69
|
+
def end_frame(start_frame_num:, file_duration:)
|
70
|
+
expected_end = (start_frame_num + frame_duration)
|
71
|
+
|
72
|
+
if file_duration < expected_end
|
73
|
+
file_duration
|
74
|
+
else
|
75
|
+
expected_end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def frame_duration
|
80
|
+
5
|
81
|
+
end
|
82
|
+
|
83
|
+
def draw_relevant_frames_from(file, file_duration, &block)
|
84
|
+
start_frame_num = start_frame(file_duration:)
|
85
|
+
end_frame_num = end_frame(start_frame_num:, file_duration:)
|
14
86
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
'
|
19
|
-
'
|
20
|
-
|
21
|
-
|
22
|
-
|
87
|
+
Rails.logger.info(
|
88
|
+
msg: "GifPreviewer draw_relevant_frames_from starting",
|
89
|
+
file_path: file.path,
|
90
|
+
'start (ss)': start_frame_num,
|
91
|
+
'end (to)': end_frame_num,
|
92
|
+
)
|
93
|
+
Timeout::timeout(MAX_PROCESSING_TIME) do
|
94
|
+
draw self.class.ffmpeg_path,
|
95
|
+
'-i', file.path,
|
96
|
+
'-filter_complex', "fps=10,scale=360:-1[s]; [s]split[a][b]; [a]palettegen[palette]; [b][palette]paletteuse",
|
97
|
+
'-f', 'gif',
|
98
|
+
'-ss', start_frame_num.to_s,
|
99
|
+
'-to', end_frame_num.to_s,
|
100
|
+
'-',
|
101
|
+
&block
|
102
|
+
end
|
23
103
|
end
|
24
104
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: video-gif-previewer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Haberer
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Generate rails active storage video previews as gifs
|
14
14
|
email: bhaberer@gmail.com
|
@@ -43,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
43
43
|
- !ruby/object:Gem::Version
|
44
44
|
version: '0'
|
45
45
|
requirements: []
|
46
|
-
rubygems_version: 3.5.
|
46
|
+
rubygems_version: 3.5.11
|
47
47
|
signing_key:
|
48
48
|
specification_version: 4
|
49
49
|
summary: ActiveStorage Gif Video Preview generation
|