WebM support

This commit is contained in:
Toks
2014-06-30 13:21:07 -04:00
parent 1a2517634a
commit a84850c094
8 changed files with 87 additions and 18 deletions

View File

@@ -43,6 +43,7 @@ gem 'statistics2'
gem 'capistrano' gem 'capistrano'
gem 'capistrano-ext' gem 'capistrano-ext'
gem 'radix62', '~> 1.0.1' gem 'radix62', '~> 1.0.1'
gem 'streamio-ffmpeg'
# needed for looser jpeg header compat # needed for looser jpeg header compat
gem 'ruby-imagespec', :require => "image_spec", :git => "https://github.com/r888888888/ruby-imagespec.git", :branch => "exif-fixes" gem 'ruby-imagespec', :require => "image_spec", :git => "https://github.com/r888888888/ruby-imagespec.git", :branch => "exif-fixes"

View File

@@ -27,7 +27,7 @@ class AmazonBackup < ActiveRecord::Base
AWS::S3::S3Object.store(File.basename(post.file_path), open(post.file_path, "rb"), Danbooru.config.amazon_s3_bucket_name, "Content-MD5" => base64_md5) AWS::S3::S3Object.store(File.basename(post.file_path), open(post.file_path, "rb"), Danbooru.config.amazon_s3_bucket_name, "Content-MD5" => base64_md5)
end end
if post.is_image? && File.exists?(post.preview_file_path) if post.has_preview? && File.exists?(post.preview_file_path)
AWS::S3::S3Object.store("preview/#{post.md5}.jpg", open(post.preview_file_path, "rb"), Danbooru.config.amazon_s3_bucket_name) AWS::S3::S3Object.store("preview/#{post.md5}.jpg", open(post.preview_file_path, "rb"), Danbooru.config.amazon_s3_bucket_name)
end end

View File

@@ -44,13 +44,13 @@ class Post < ActiveRecord::Base
module FileMethods module FileMethods
def distribute_files def distribute_files
RemoteFileManager.new(file_path).distribute RemoteFileManager.new(file_path).distribute
RemoteFileManager.new(preview_file_path).distribute if is_image? RemoteFileManager.new(preview_file_path).distribute if has_preview?
RemoteFileManager.new(large_file_path).distribute if has_large? RemoteFileManager.new(large_file_path).distribute if has_large?
end end
def delete_remote_files def delete_remote_files
RemoteFileManager.new(file_path).delete RemoteFileManager.new(file_path).delete
RemoteFileManager.new(preview_file_path).delete if is_image? RemoteFileManager.new(preview_file_path).delete if has_preview?
RemoteFileManager.new(large_file_path).delete if has_large? RemoteFileManager.new(large_file_path).delete if has_large?
end end
@@ -93,7 +93,7 @@ class Post < ActiveRecord::Base
end end
def preview_file_url def preview_file_url
if !is_image? if !has_preview?
return "/images/download-preview.png" return "/images/download-preview.png"
end end
@@ -127,6 +127,18 @@ class Post < ActiveRecord::Base
def is_flash? def is_flash?
file_ext =~ /swf/i file_ext =~ /swf/i
end end
def is_video?
file_ext =~ /webm/i
end
def has_preview?
is_image? || is_video?
end
def has_dimensions?
is_image? || is_flash? || is_video?
end
end end
module ImageMethods module ImageMethods

View File

@@ -51,7 +51,7 @@ class Upload < ActiveRecord::Base
def validate_file_content_type def validate_file_content_type
unless is_valid_content_type? unless is_valid_content_type?
raise "invalid content type (only JPEG, PNG, GIF, and SWF files are allowed)" raise "invalid content type (only JPEG, PNG, GIF, SWF, and WebM files are allowed)"
end end
end end
@@ -72,6 +72,18 @@ class Upload < ActiveRecord::Base
return false return false
end end
end end
def validate_no_audio
if is_video? && video.audio_channels.present?
raise "video must not have audio channels"
end
end
def validate_video_duration
if is_video? && video.duration > 120
raise "video must not be longer than 2 minutes"
end
end
end end
module ConversionMethods module ConversionMethods
@@ -90,6 +102,8 @@ class Upload < ActiveRecord::Base
calculate_hash(file_path) calculate_hash(file_path)
validate_md5_uniqueness validate_md5_uniqueness
validate_md5_confirmation validate_md5_confirmation
validate_no_audio
validate_video_duration
calculate_file_size(file_path) calculate_file_size(file_path)
if has_dimensions? if has_dimensions?
calculate_dimensions(file_path) calculate_dimensions(file_path)
@@ -151,15 +165,23 @@ class Upload < ActiveRecord::Base
end end
def is_image? def is_image?
["jpg", "gif", "png"].include?(file_ext) %w(jpg gif png).include?(file_ext)
end
def is_flash?
%w(swf).include?(file_ext)
end
def is_video?
%w(webm).include?(file_ext)
end end
end end
module ResizerMethods module ResizerMethods
def generate_resizes(source_path) def generate_resizes(source_path)
if is_image? generate_resize_for(Danbooru.config.small_image_width, Danbooru.config.small_image_width, source_path, 85)
generate_resize_for(Danbooru.config.small_image_width, Danbooru.config.small_image_width, source_path, 85) if is_image? && image_width > Danbooru.config.large_image_width
generate_resize_for(Danbooru.config.large_image_width, nil, source_path) if image_width > Danbooru.config.large_image_width generate_resize_for(Danbooru.config.large_image_width, nil, source_path)
end end
end end
@@ -168,29 +190,45 @@ class Upload < ActiveRecord::Base
raise Error.new("file not found") raise Error.new("file not found")
end end
Danbooru.resize(source_path, resized_file_path_for(width), width, height, quality) if is_image?
Danbooru.resize(source_path, resized_file_path_for(width), width, height, quality)
elsif is_video?
dimension_ratio = image_width.to_f / image_height
if dimension_ratio > 1
height = (width / dimension_ratio).to_i
else
width = (height * dimension_ratio).to_i
end
video.screenshot(resized_file_path_for(width), {:seek_time => 0, :resolution => "#{width}x#{height}"})
FileUtils.chmod(0664, resized_file_path_for(width))
end
end end
end end
module DimensionMethods module DimensionMethods
# Figures out the dimensions of the image. # Figures out the dimensions of the image.
def calculate_dimensions(file_path) def calculate_dimensions(file_path)
File.open(file_path, "rb") do |file| if is_video?
image_size = ImageSpec.new(file) self.image_width = video.width
self.image_width = image_size.width self.image_height = video.height
self.image_height = image_size.height else
File.open(file_path, "rb") do |file|
image_size = ImageSpec.new(file)
self.image_width = image_size.width
self.image_height = image_size.height
end
end end
end end
# Does this file have image dimensions? # Does this file have image dimensions?
def has_dimensions? def has_dimensions?
%w(jpg gif png swf).include?(file_ext) %w(jpg gif png swf webm).include?(file_ext)
end end
end end
module ContentTypeMethods module ContentTypeMethods
def is_valid_content_type? def is_valid_content_type?
file_ext =~ /jpg|gif|png|swf/ file_ext =~ /jpg|gif|png|swf|webm/
end end
def content_type_to_file_ext(content_type) def content_type_to_file_ext(content_type)
@@ -207,6 +245,9 @@ class Upload < ActiveRecord::Base
when "application/x-shockwave-flash" when "application/x-shockwave-flash"
"swf" "swf"
when "video/webm"
"webm"
else else
"bin" "bin"
end end
@@ -226,6 +267,9 @@ class Upload < ActiveRecord::Base
when /^CWS/, /^FWS/, /^ZWS/ when /^CWS/, /^FWS/, /^ZWS/
"application/x-shockwave-flash" "application/x-shockwave-flash"
when /^\x1a\x45\xdf\xa3/
"video/webm"
else else
"application/octet-stream" "application/octet-stream"
end end
@@ -320,6 +364,12 @@ class Upload < ActiveRecord::Base
end end
end end
module VideoMethods
def video
@video ||= FFMPEG::Movie.new(file_path)
end
end
module SearchMethods module SearchMethods
def uploaded_by(user_id) def uploaded_by(user_id)
where("uploader_id = ?", user_id) where("uploader_id = ?", user_id)
@@ -381,6 +431,7 @@ class Upload < ActiveRecord::Base
include CgiFileMethods include CgiFileMethods
include StatusMethods include StatusMethods
include UploaderMethods include UploaderMethods
include VideoMethods
extend SearchMethods extend SearchMethods
include ApiMethods include ApiMethods

View File

@@ -155,6 +155,8 @@ class PostPresenter < Presenter
if @post.is_flash? if @post.is_flash?
template.render("posts/partials/show/flash", :post => @post) template.render("posts/partials/show/flash", :post => @post)
elsif @post.is_video?
template.render("posts/partials/show/video", :post => @post)
elsif !@post.is_image? elsif !@post.is_image?
template.render("posts/partials/show/download", :post => @post) template.render("posts/partials/show/download", :post => @post)
elsif @post.is_image? elsif @post.is_image?

View File

@@ -38,7 +38,7 @@
<li> <li>
<strong>Size:</strong> <strong>Size:</strong>
<%= number_to_human_size(post.file_size) %> <%= number_to_human_size(post.file_size) %>
<% if post.is_image? %> <% if post.has_dimensions? %>
(<%= post.image_width %>x<%= post.image_height %>) (<%= post.image_width %>x<%= post.image_height %>)
<% end %> <% end %>
</li> </li>

View File

@@ -7,7 +7,7 @@
<% end %> <% end %>
<li> <li>
Size: <%= link_to_if post.visible?, number_to_human_size(post.file_size), post.file_url %> Size: <%= link_to_if post.visible?, number_to_human_size(post.file_size), post.file_url %>
<% if post.is_image? %> <% if post.has_dimensions? %>
(<%= post.image_width %>x<%= post.image_height %>) (<%= post.image_width %>x<%= post.image_height %>)
<% end %> <% end %>
</li> </li>

View File

@@ -0,0 +1,3 @@
<%= content_tag(:video, nil, :width => post.image_width, :height => post.image_height, :autoplay => true, :loop => true, :src => post.file_url) %>
<p><%= link_to "Save this video (right click and save)", post.file_url %></p>