From 96ba3482b96504d7a8e2a7dc7dbfea41c86be74f Mon Sep 17 00:00:00 2001 From: DJ Sundog Date: Sat, 7 Oct 2017 19:54:10 +0000 Subject: [PATCH 1/5] adding support for audio uploads, transcoded to mp4 videos --- app/models/media_attachment.rb | 28 ++++++++++++++++++--- app/serializers/initial_state_serializer.rb | 2 +- config/application.rb | 1 + lib/paperclip/audio_transcoder.rb | 15 +++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 lib/paperclip/audio_transcoder.rb diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index e4a974f968..93ff43d58c 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -23,15 +23,31 @@ require 'mime/types' class MediaAttachment < ApplicationRecord self.inheritance_column = nil - enum type: [:image, :gifv, :video, :unknown] + enum type: [:image, :gifv, :video, :audio, :unknown] IMAGE_FILE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif'].freeze VIDEO_FILE_EXTENSIONS = ['.webm', '.mp4', '.m4v'].freeze + AUDIO_FILE_EXTENSIONS = ['.mp3', '.m4a', '.wav', '.ogg'].freeze IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze VIDEO_MIME_TYPES = ['video/webm', 'video/mp4'].freeze + AUDIO_MIME_TYPES = ['audio/mpeg', 'audio/mp4', 'audio/vnd.wav', 'audio/wav', 'audio/x-wav', 'audio/x-wave', 'audio/ogg',].freeze IMAGE_STYLES = { original: '1280x1280>', small: '400x400>' }.freeze + AUDIO_STYLES = { + original: { + format: 'mp4', + convert_options: { + output: { + filter_complex: '"[0:a]compand,showwaves=s=640x360:mode=line,format=yuv420p[v]"', + map: '"[v]" -map 0:a', + threads: 2, + vcodec: 'libx264', + acodec: 'aac', + }, + }, + }, + }.freeze VIDEO_STYLES = { small: { convert_options: { @@ -54,7 +70,7 @@ class MediaAttachment < ApplicationRecord include Remotable - validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES + validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES + AUDIO_MIME_TYPES validates_attachment_size :file, less_than: 8.megabytes validates :account, presence: true @@ -107,6 +123,8 @@ class MediaAttachment < ApplicationRecord } elsif IMAGE_MIME_TYPES.include? f.instance.file_content_type IMAGE_STYLES + elsif AUDIO_MIME_TYPES.include? f.instance.file_content_type + AUDIO_STYLES else VIDEO_STYLES end @@ -117,6 +135,8 @@ class MediaAttachment < ApplicationRecord [:gif_transcoder] elsif VIDEO_MIME_TYPES.include? f.file_content_type [:video_transcoder] + elsif AUDIO_MIME_TYPES.include? f.file_content_type + [:audio_transcoder] else [:thumbnail] end @@ -137,8 +157,8 @@ class MediaAttachment < ApplicationRecord end def set_type_and_extension - self.type = VIDEO_MIME_TYPES.include?(file_content_type) ? :video : :image - extension = appropriate_extension + self.type = VIDEO_MIME_TYPES.include?(file_content_type) ? :video : AUDIO_MIME_TYPES.include?(file_content_type) ? :audio : :image + extension = AUDIO_MIME_TYPES.include?(file_content_type) ? '.mp4' : appropriate_extension basename = Paperclip::Interpolations.basename(file, :original) file.instance_write :file_name, [basename, extension].delete_if(&:blank?).join('.') end diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index e2f15a6010..0992771fc4 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -52,6 +52,6 @@ class InitialStateSerializer < ActiveModel::Serializer end def media_attachments - { accept_content_types: MediaAttachment::IMAGE_FILE_EXTENSIONS + MediaAttachment::VIDEO_FILE_EXTENSIONS + MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES } + { accept_content_types: MediaAttachment::IMAGE_FILE_EXTENSIONS + MediaAttachment::VIDEO_FILE_EXTENSIONS + MediaAttachment::AUDIO_FILE_EXTENSIONS + MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES + MediaAttachment::AUDIO_MIME_TYPES } end end diff --git a/config/application.rb b/config/application.rb index eb89f0a105..db53b8c840 100644 --- a/config/application.rb +++ b/config/application.rb @@ -9,6 +9,7 @@ Bundler.require(*Rails.groups) require_relative '../app/lib/exceptions' require_relative '../lib/paperclip/gif_transcoder' require_relative '../lib/paperclip/video_transcoder' +require_relative '../lib/paperclip/audio_transcoder' require_relative '../lib/mastodon/version' Dotenv::Railtie.load diff --git a/lib/paperclip/audio_transcoder.rb b/lib/paperclip/audio_transcoder.rb new file mode 100644 index 0000000000..484d694d72 --- /dev/null +++ b/lib/paperclip/audio_transcoder.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Paperclip + class AudioTranscoder < Paperclip::Processor + def make + final_file = Paperclip::Transcoder.make(file, options, attachment) + + attachment.instance.file_file_name = 'media.mp4' + attachment.instance.file_content_type = 'video/mp4' + attachment.instance.type = MediaAttachment.types[:video] + + final_file + end + end +end From 6ca03a7f5861bf03e00f86342409711e078e1131 Mon Sep 17 00:00:00 2001 From: DJ Sundog Date: Sat, 7 Oct 2017 19:59:22 +0000 Subject: [PATCH 2/5] add faststart to audio transcoding --- app/models/media_attachment.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 93ff43d58c..1bea8c872c 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -44,6 +44,7 @@ class MediaAttachment < ApplicationRecord threads: 2, vcodec: 'libx264', acodec: 'aac', + movflags: '+faststart', }, }, }, From 979b0d66a7e0a49646b396c2486a762a9bb57a05 Mon Sep 17 00:00:00 2001 From: DJ Sundog Date: Sat, 7 Oct 2017 13:53:46 -0700 Subject: [PATCH 3/5] update indentation --- app/models/media_attachment.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 1bea8c872c..65ff893a80 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -36,17 +36,17 @@ class MediaAttachment < ApplicationRecord IMAGE_STYLES = { original: '1280x1280>', small: '400x400>' }.freeze AUDIO_STYLES = { original: { - format: 'mp4', - convert_options: { - output: { - filter_complex: '"[0:a]compand,showwaves=s=640x360:mode=line,format=yuv420p[v]"', - map: '"[v]" -map 0:a', - threads: 2, - vcodec: 'libx264', - acodec: 'aac', - movflags: '+faststart', - }, + format: 'mp4', + convert_options: { + output: { + filter_complex: '"[0:a]compand,showwaves=s=640x360:mode=line,format=yuv420p[v]"', + map: '"[v]" -map 0:a', + threads: 2, + vcodec: 'libx264', + acodec: 'aac', + movflags: '+faststart', }, + }, }, }.freeze VIDEO_STYLES = { From e10cff8226172842376c30fb3cb098a570535400 Mon Sep 17 00:00:00 2001 From: DJ Sundog Date: Sat, 7 Oct 2017 13:55:11 -0700 Subject: [PATCH 4/5] update indentation --- lib/paperclip/audio_transcoder.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/paperclip/audio_transcoder.rb b/lib/paperclip/audio_transcoder.rb index 484d694d72..388763de8c 100644 --- a/lib/paperclip/audio_transcoder.rb +++ b/lib/paperclip/audio_transcoder.rb @@ -3,13 +3,13 @@ module Paperclip class AudioTranscoder < Paperclip::Processor def make - final_file = Paperclip::Transcoder.make(file, options, attachment) + final_file = Paperclip::Transcoder.make(file, options, attachment) + + attachment.instance.file_file_name = 'media.mp4' + attachment.instance.file_content_type = 'video/mp4' + attachment.instance.type = MediaAttachment.types[:video] - attachment.instance.file_file_name = 'media.mp4' - attachment.instance.file_content_type = 'video/mp4' - attachment.instance.type = MediaAttachment.types[:video] - - final_file + final_file end end end From 85d5da86dfd3589e345a68c19fff7d7bc2524532 Mon Sep 17 00:00:00 2001 From: DJ Sundog Date: Sat, 7 Oct 2017 16:14:34 -0700 Subject: [PATCH 5/5] raise Mastodon::ValidationError if audio file duration is over 60 secs --- lib/paperclip/audio_transcoder.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/paperclip/audio_transcoder.rb b/lib/paperclip/audio_transcoder.rb index 388763de8c..631ccb0be0 100644 --- a/lib/paperclip/audio_transcoder.rb +++ b/lib/paperclip/audio_transcoder.rb @@ -3,6 +3,12 @@ module Paperclip class AudioTranscoder < Paperclip::Processor def make + meta = ::Av.cli.identify(@file.path) + # {:length=>"0:00:02.14", :duration=>2.14, :audio_encode=>"mp3", :audio_bitrate=>"44100 Hz", :audio_channels=>"mono"} + if meta[:duration] > 60.0 + raise Mastodon::ValidationError, "Audio uploads must be less than 60 seconds in length." + end + final_file = Paperclip::Transcoder.make(file, options, attachment) attachment.instance.file_file_name = 'media.mp4'