Replace streamio-ffmpeg library.
Replace the streamio-ffmpeg library with our own very thin FFmpeg wrapper.
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
require "shellwords"
|
||||
|
||||
# A wrapper for the ffmpeg command.
|
||||
class FFmpeg
|
||||
extend Memoist
|
||||
|
||||
class Error < StandardError; end
|
||||
|
||||
attr_reader :file
|
||||
|
||||
# Operate on a file with FFmpeg.
|
||||
@@ -16,10 +23,52 @@ class FFmpeg
|
||||
|
||||
# https://ffmpeg.org/ffmpeg.html#Main-options
|
||||
# https://ffmpeg.org/ffmpeg-filters.html#thumbnail
|
||||
ffmpeg_out, status = Open3.capture2e("ffmpeg -i #{file.path} -vf thumbnail=300 -frames:v 1 -y #{vp.path}")
|
||||
raise "ffmpeg failed: #{ffmpeg_out}" if !status.success?
|
||||
Rails.logger.debug(ffmpeg_out)
|
||||
output = shell!("ffmpeg -i #{file.path.shellescape} -vf thumbnail=300 -frames:v 1 -y #{vp.path.shellescape}")
|
||||
Rails.logger.debug(output)
|
||||
|
||||
MediaFile.open(vp)
|
||||
end
|
||||
|
||||
# Get file metadata using ffprobe.
|
||||
# @see https://ffmpeg.org/ffprobe.html
|
||||
# @see https://gist.github.com/nrk/2286511
|
||||
# @return [Hash] a hash of the file's metadata
|
||||
def metadata
|
||||
output = shell!("ffprobe -v quiet -print_format json -show_format -show_streams #{file.path.shellescape}")
|
||||
json = JSON.parse(output)
|
||||
json.with_indifferent_access
|
||||
end
|
||||
|
||||
def width
|
||||
video_channels.first[:width]
|
||||
end
|
||||
|
||||
def height
|
||||
video_channels.first[:height]
|
||||
end
|
||||
|
||||
def duration
|
||||
metadata.dig(:format, :duration).to_f
|
||||
end
|
||||
|
||||
def video_channels
|
||||
metadata[:streams].select { |stream| stream[:codec_type] == "video" }
|
||||
end
|
||||
|
||||
def audio_channels
|
||||
metadata[:streams].select { |stream| stream[:codec_type] == "audio" }
|
||||
end
|
||||
|
||||
def has_audio?
|
||||
audio_channels.present?
|
||||
end
|
||||
|
||||
def shell!(command)
|
||||
program = command.shellsplit.first
|
||||
output, status = Open3.capture2e(command)
|
||||
raise Error, "#{program} failed: #{output}" if !status.success?
|
||||
output
|
||||
end
|
||||
|
||||
memoize :metadata
|
||||
end
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
#
|
||||
# @see https://github.com/streamio/streamio-ffmpeg
|
||||
class MediaFile::Video < MediaFile
|
||||
delegate :duration, :has_audio?, to: :video
|
||||
|
||||
def dimensions
|
||||
[video.width, video.height]
|
||||
end
|
||||
|
||||
def duration
|
||||
video.duration
|
||||
end
|
||||
|
||||
def preview(max_width, max_height)
|
||||
preview_frame.preview(max_width, max_height)
|
||||
end
|
||||
@@ -19,20 +17,14 @@ class MediaFile::Video < MediaFile
|
||||
preview_frame.crop(max_width, max_height)
|
||||
end
|
||||
|
||||
def has_audio?
|
||||
video.audio_channels.present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def video
|
||||
raise NotImplementedError, "can't process videos: ffmpeg or mkvmerge not installed" unless self.class.videos_enabled?
|
||||
|
||||
FFMPEG::Movie.new(file.path)
|
||||
FFmpeg.new(file)
|
||||
end
|
||||
|
||||
def preview_frame
|
||||
FFmpeg.new(file).smart_video_preview
|
||||
video.smart_video_preview
|
||||
end
|
||||
|
||||
memoize :video, :preview_frame, :dimensions, :duration, :has_audio?
|
||||
|
||||
Reference in New Issue
Block a user