Refactors the upload process to pass around temp files, rather than passing around file paths and directly writing output to the local filesystem. This way we can pass the storage manager the preview / sample / original temp files, so it can deal with storage itself. * Change Download::File#download! to return a temp file. * Change DanbooruImageResizer and PixivUgoiraConverter to accept/return temp files instead of file paths. * Change Upload#generate_resizes to return temp files for previews and samples. * Change Upload#generate_resizes to generate ugoira .webm samples synchronously instead of asynchronously.
77 lines
2.9 KiB
Ruby
77 lines
2.9 KiB
Ruby
class PixivUgoiraConverter
|
|
def self.generate_webm(ugoira_file, frame_data)
|
|
folder = Zip::File.new(ugoira_file.path)
|
|
output_file = Tempfile.new(binmode: true)
|
|
write_path = output_file.path
|
|
|
|
Dir.mktmpdir do |tmpdir|
|
|
FileUtils.mkdir_p("#{tmpdir}/images")
|
|
folder.each_with_index do |file, i|
|
|
path = File.join(tmpdir, "images", file.name)
|
|
file.extract(path)
|
|
end
|
|
|
|
# Duplicate last frame to avoid it being displayed only for a very short amount of time.
|
|
last_file_name = folder.to_a.last.name
|
|
last_file_name =~ /\A(\d{6})(\.\w{,4})\Z/
|
|
new_last_index = $1.to_i + 1
|
|
file_ext = $2
|
|
new_last_filename = ("%06d" % new_last_index) + file_ext
|
|
path_from = File.join(tmpdir, "images", last_file_name)
|
|
path_to = File.join(tmpdir, "images", new_last_filename)
|
|
FileUtils.cp(path_from, path_to)
|
|
|
|
delay_sum = 0
|
|
timecodes_path = File.join(tmpdir, "timecodes.tc")
|
|
File.open(timecodes_path, "w+") do |f|
|
|
f.write("# timecode format v2\n")
|
|
frame_data.each do |img|
|
|
f.write("#{delay_sum}\n")
|
|
delay_sum += (img["delay"] || img["delay_msec"])
|
|
end
|
|
f.write("#{delay_sum}\n")
|
|
f.write("#{delay_sum}\n")
|
|
end
|
|
|
|
ext = folder.first.name.match(/\.(\w{,4})$/)[1]
|
|
ffmpeg_out, status = Open3.capture2e("ffmpeg -i #{tmpdir}/images/%06d.#{ext} -codec:v libvpx -crf 4 -b:v 5000k -an #{tmpdir}/tmp.webm")
|
|
|
|
if !status.success?
|
|
Rails.logger.error "[write_webm] ******************************"
|
|
Rails.logger.error "[write_webm] failed write_path=#{write_path}"
|
|
Rails.logger.error "[write_webm] ffmepg output:"
|
|
ffmpeg_out.split(/\n/).each do |line|
|
|
Rails.logger.error "[write_webm][ffmpeg] #{line}"
|
|
end
|
|
Rails.logger.error "[write_webm] ******************************"
|
|
return
|
|
end
|
|
|
|
mkvmerge_out, status = Open3.capture2e("mkvmerge -o #{write_path} --webm --timecodes 0:#{tmpdir}/timecodes.tc #{tmpdir}/tmp.webm")
|
|
|
|
if !status.success?
|
|
Rails.logger.error "[write_webm] ******************************"
|
|
Rails.logger.error "[write_webm] failed write_path=#{write_path}"
|
|
Rails.logger.error "[write_webm] mkvmerge output:"
|
|
mkvmerge_out.split(/\n/).each do |line|
|
|
Rails.logger.error "[write_webm][mkvmerge] #{line}"
|
|
end
|
|
Rails.logger.error "[write_webm] ******************************"
|
|
return
|
|
end
|
|
end
|
|
|
|
output_file
|
|
end
|
|
|
|
def self.generate_preview(ugoira_file)
|
|
file = Tempfile.new(binmode: true)
|
|
zipfile = Zip::File.new(ugoira_file.path)
|
|
zipfile.entries.first.extract(file.path) { true } # 'true' means overwrite the existing tempfile.
|
|
|
|
DanbooruImageResizer.resize(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 85)
|
|
ensure
|
|
file.close!
|
|
end
|
|
end
|