integrate ugoiras into zip+webm+preview

This commit is contained in:
r888888888
2014-10-09 17:05:47 -07:00
parent 0a61aac231
commit 3bb06c2be4
28 changed files with 1800 additions and 1125 deletions

View File

@@ -1,43 +1,11 @@
class PixivUgoiraConverter
attr_reader :agent, :url, :write_path, :format
def initialize(url, write_path, format)
@url = url
@write_path = write_path
@format = format
def convert(source_path, output_path, preview_path, frame_data)
folder = unpack(File.open(source_path))
write_webm(folder, output_path, frame_data)
write_preview(folder, preview_path)
end
def process!
folder = unpack(fetch_zipped_body)
if format == :gif
write_gif(folder)
elsif format == :webm
write_webm(folder)
elsif format == :apng
write_apng(folder)
end
end
def write_gif(folder)
anim = Magick::ImageList.new
delay_sum = 0
folder.each_with_index do |file, i|
image_blob = file.get_input_stream.read
image = Magick::Image.from_blob(image_blob).first
image.ticks_per_second = 1000
delay = @frame_data[i]["delay"]
rounded_delay = (delay_sum + delay).round(-1) - delay_sum.round(-1)
image.delay = rounded_delay
delay_sum += delay
anim << image
end
anim = anim.optimize_layers(Magick::OptimizeTransLayer)
anim.write("gif:" + write_path)
end
def write_webm(folder)
def write_webm(folder, write_path, frame_data)
Dir.mktmpdir do |tmpdir|
FileUtils.mkdir_p("#{tmpdir}/images")
folder.each_with_index do |file, i|
@@ -62,7 +30,7 @@ class PixivUgoiraConverter
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|
frame_data.each do |img|
f.write("#{delay_sum}\n")
delay_sum += img["delay"]
end
@@ -71,68 +39,21 @@ class PixivUgoiraConverter
end
ext = folder.first.name.match(/\.(\w{,4})$/)[1]
system("ffmpeg -i #{tmpdir}/images/%06d.#{ext} -codec:v libvpx -crf 4 -b:v 5000k -an #{tmpdir}/tmp.webm")
system("mkvmerge -o #{write_path} --webm --timecodes 0:#{tmpdir}/timecodes.tc #{tmpdir}/tmp.webm")
system("ffmpeg -loglevel quiet -i #{tmpdir}/images/%06d.#{ext} -codec:v libvpx -crf 4 -b:v 5000k -an #{tmpdir}/tmp.webm")
system("mkvmerge -q -o #{write_path} --webm --timecodes 0:#{tmpdir}/timecodes.tc #{tmpdir}/tmp.webm")
end
end
def write_apng(folder)
Dir.mktmpdir do |tmpdir|
folder.each_with_index do |file, i|
frame_path = File.join(tmpdir, "frame#{"%03d" % i}.png")
delay_path = File.join(tmpdir, "frame#{"%03d" % i}.txt")
image_blob = file.get_input_stream.read
delay = @frame_data[i]["delay"]
image = Magick::Image.from_blob(image_blob).first
image.format = "PNG"
image.write(frame_path)
File.open(delay_path, "wb") do |f|
f.write("delay=#{delay}/1000")
end
end
system("apngasm -o -F #{write_path} #{tmpdir}/frame*.png")
end
def write_preview(folder, path)
file = folder.first
image_blob = file.get_input_stream.read
image = Magick::Image.from_blob(image_blob).first
image.write(path)
end
def unpack(zipped_body)
def unpack(zip_file)
folder = Zip::CentralDirectory.new
folder.read_from_stream(StringIO.new(zipped_body))
folder.read_from_stream(zip_file)
folder
end
def fetch_zipped_body
zip_body = nil
zip_url, @frame_data = fetch_frames
Downloads::File.new(zip_url, nil).http_get_streaming do |response|
zip_body = response.body
end
zip_body
end
def agent
@agent ||= Sources::Strategies::Pixiv.new(url).agent
end
def fetch_frames
agent.get(url) do |page|
# Get the zip url and frame delay by parsing javascript contained in a <script> tag on the page.
# Not a neat solution, but I haven't found any other location that has the frame delays listed.
scripts = page.search("body script").find_all do |node|
node.text =~ /_ugoira600x600\.zip/
end
if scripts.any?
javascript = scripts.first.text
json = javascript.match(/;pixiv\.context\.ugokuIllustData\s+=\s+(\{.+?\});(?:$|pixiv\.context)/)[1]
data = JSON.parse(json)
zip_url = data["src"].sub("_ugoira600x600.zip", "_ugoira1920x1080.zip")
frame_data = data["frames"]
return [zip_url, frame_data]
else
raise "Can't find javascript with frame data"
end
end
end
end