12/08/2018, 13:50

Upload và convert video với gem paperclip-av-transcoder

Upload File là một trong những công việc hay gặp trong lập trình web, trong đó việc upload các video lên luôn là công việc khó khăn do khả năng play video của các trình duyệt chỉ hỗ trợ một vài định dạng , thế nên việc convert sang các định dạng chuẩn phù hợp với trình duyệt là công việc cần ...

Upload File là một trong những công việc hay gặp trong lập trình web, trong đó việc upload các video lên luôn là công việc khó khăn do khả năng play video của các trình duyệt chỉ hỗ trợ một vài định dạng , thế nên việc convert sang các định dạng chuẩn phù hợp với trình duyệt là công việc cần thiết. Hôm nay mình sẽ hướng dẫn các bạn cách upload video và convert video về các định dạng thông qua gem "paperclip", "~> 5.0.0", gem 'paperclip-av-transcoder' và thư viện ffmpeg.

Thư viện ffmpeg là một thư viện convert video khá nổi tiếng để cài đặt thư viện này:

brew options ffmpeg
brew install ffmpeg --with-fdk-aac --with-ffplay --with-freetype --with-frei0r --with-libas
sudo add-apt-repository ppa:mc3man/trusty-media
sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install ffmpeg

Trước khi upload video. Chúng ta sẽ tìm hiểu một chút về html5 với video. Hiện nay HTML5 đã hỗ trợ rất tốt việc hiển thị và chơi video trên trình duyệt web, tuy nhiên không phải format video nào HTML 5 cũng hố trợ và không phải trình duyệt nào cũng hỗ trợ video. Một vài format hay được hỗ trợ webm, mp4/h264, ogg. Chi tiết các bạn xem ở đây và format video support ở đây.Mình xin phép không nói ở đây vì đây không phải là trọng tâm của bài viết.

Trở lại với chủ đề chính , sau một hồi setup hệ thống , cài đặt các kiểu , chúng ta bắt đầu vọc qua một ứng dụng.

Chúng ta sẽ xây dựng một ứng cho phép post các chủ đề với tiêu đề , nội dung và có thể đính kèm video.

Bước 1: Set up ứng dụng:

rails new upload
rails g scaffold Post title:string content:text

Thêm gem

gem "paperclip", "~> 5.0.0"
gem "paperclip-av-transcoder"

Thêm attachment cho Posts

rails g migration AddAttachmentColumnsToPosts

Trong migration thêm vào

add_attachment :posts, :attachment
rake db:migrate

Setup root cho routes.rb

root "posts#index"

form.html.erb .Thêm vào:

<%= form_for @post, html: {multipart: true} do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
      <% @post.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :content %><br>
    <%= f.text_area :content %>
  </div>
  <div class="field">
    <%= f.file_field :attachment %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Trong show.html.erb, sử dụng thẻ video_tag để hiện thị video:

<p id="notice"><%= notice %></p>

<p>
  <strong>Title:</strong>
  <%= @post.title %>
</p>

<p>
  <strong>Content:</strong>
  <%= @post.content %>
</p>

<p>
  <strong>Video:</strong>
  <%= video_tag @post.attachment.url,
    controls: true, style: "max-awidth: 100%;" %>
</p>

<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>

Setup cho model post.rb:

class Post < ActiveRecord::Base
  has_attached_file :attachment, styles: {
    medium: {geometry: "640x480", format:'mp4'},
    thumb: {geometry: "100x100#", format:'jpg', time: 10}
    }, processors: [:transcoder]

  validates_attachment_content_type :attachment, content_type: /Avideo/.*/
  validates_attachment :attachment, size: {less_than: 130.megabytes}
end

Một vài chú ý , chúng ta có thể convert theo định dạng cũng như kích thước tùy ý nhờ 2 thuộc tính geometry và format. Định dạng mp4 được mặc định sử dụng codec H.264, có khá nhiều codec khác nhau cho định dạng mp4 này.Chúng ta có thể xem các codecs cũng như các encoders bằng các câu lệnh sau:

ffmpeg -codecs
ffmpeg -encoders

Thêm tùy chọn cho việc convert với convert_options:

has_attached_file :attachment, styles: {
  medium: {geometry: "640x480", format:'mp4', convert_options: {
    input: {},
    output: {
      vcodec: 'libx264',
      movflags: '+faststart',
      strict: :experimental
    }
  }},thumb: {geometry: "100x100#", format:'jpg', time: 10}
}, processors: [:transcoder]

Quá trình convert video là quá trình rất tốn tài nguyên vì thế cần phải cân nhắc trước khi sử dụng . Bạn cũng có thể đẩy các process này vào background .Và đó là phần bài tập nâng cao dành cho các bạn.

Xin chân thành cảm ơn các bạn đã quan tâm theo dõi. Hẹn gặp lại các bạn trong các chủ đề tiếp theo.

Source code.

0