Files
danbooru/app/logical/pixiv_ugoira_converter.rb
evazion c76463f34d uploads: use storage manager to distribute files.
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.
2018-03-20 19:49:06 -05:00

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