
Recherche avancée
Médias (1)
-
The pirate bay depuis la Belgique
1er avril 2013, par
Mis à jour : Avril 2013
Langue : français
Type : Image
Autres articles (48)
-
La file d’attente de SPIPmotion
28 novembre 2010, parUne file d’attente stockée dans la base de donnée
Lors de son installation, SPIPmotion crée une nouvelle table dans la base de donnée intitulée spip_spipmotion_attentes.
Cette nouvelle table est constituée des champs suivants : id_spipmotion_attente, l’identifiant numérique unique de la tâche à traiter ; id_document, l’identifiant numérique du document original à encoder ; id_objet l’identifiant unique de l’objet auquel le document encodé devra être attaché automatiquement ; objet, le type d’objet auquel (...) -
(Dés)Activation de fonctionnalités (plugins)
18 février 2011, parPour gérer l’ajout et la suppression de fonctionnalités supplémentaires (ou plugins), MediaSPIP utilise à partir de la version 0.2 SVP.
SVP permet l’activation facile de plugins depuis l’espace de configuration de MediaSPIP.
Pour y accéder, il suffit de se rendre dans l’espace de configuration puis de se rendre sur la page "Gestion des plugins".
MediaSPIP est fourni par défaut avec l’ensemble des plugins dits "compatibles", ils ont été testés et intégrés afin de fonctionner parfaitement avec chaque (...) -
Activation de l’inscription des visiteurs
12 avril 2011, parIl est également possible d’activer l’inscription des visiteurs ce qui permettra à tout un chacun d’ouvrir soit même un compte sur le canal en question dans le cadre de projets ouverts par exemple.
Pour ce faire, il suffit d’aller dans l’espace de configuration du site en choisissant le sous menus "Gestion des utilisateurs". Le premier formulaire visible correspond à cette fonctionnalité.
Par défaut, MediaSPIP a créé lors de son initialisation un élément de menu dans le menu du haut de la page menant (...)
Sur d’autres sites (8027)
-
How do I get videos to upload using ruby on rails carrierwave-video ?
9 juillet 2016, par EricUpdated as of July 9, 2016
I tried to follow the instructions on the github website for the video uploader process using carrierwave-video gem but get an error that says the file or directory mmpeg -i doesn’t exist.
The upload path for images functions correctly, just not the video one.
I have added all of the following code necessary to help solve the error and minified as much as i possibly could.
Video uploader code using carrierwave
class VideoUploader < CarrierWave::Uploader::Base
include CarrierWave::Video
storage :file
version :mp4 do
process :encode_video => [:mp4, resolution: "100x100"]
end
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
endHere is the movie controller code that handles uploading of videos
class MoviesController < ApplicationController
include MoviesHelper
def index
mode "index"
end
def show
mode "show"
end
def new
mode "new"
end
def edit
mode "edit"
end
def create
mode "create"
end
def update
mode "update"
end
def destroy
mode "destroy"
end
def review
mode "review"
end
def approve
mode "approve"
end
def deny
mode "deny"
end
endHere is the model data for the movie that goes with it
class Movie < ActiveRecord::Base
attr_accessible :created_on, :description, :maintenance, :reviewed, :subplaylist_id, :title, :user_id, :video, :remote_video_url
belongs_to :user
belongs_to :subplaylist
mount_uploader :video, VideoUploader
endHere is where the movie is supposed to be displayed but it is not working
<% provide(:title, "Movie: Where movies are made!") %>
<% provide(:keywords, "movies, video") %>
<% provide(:description, "This is the place where users showcase their wonderful video talent.") %>
<p><%= notice %></p>
<h1 class="pageheader"><%= @movie.title %></h1>
<br />
<p class="pagetext"><%= video_tag(@movie.video_url.to_s, controls: true, class: "imagebox") %></p>
<p class="pagetext"><%= @movie.description %></p>
<p class="pagetext">Created on: <%= @movie.created_on.strftime("%B-%d-%Y") %></p>
<p class="pagetext">Owner: <%= getType(@movie.user) %><%= link_to @movie.user.vname, user_path(@movie.user) %></p>
<br />
<p class="pagetext"><%= link_to 'Back', mainplaylist_subplaylist_path(@subplaylist.mainplaylist, @movie.subplaylist) %></p>Here is where the movie new action is
<% provide(:title, "Movie: Create new movies here!") %>
<% provide(:description, "New movies are uploaded only to the site when the movie gets approved.") %>
<h1 class="pagetextheader">New movie</h1>
<%= render 'form' %>
<p class="pagetext"><%= link_to 'Back', mainplaylist_subplaylist_path(@subplaylist.mainplaylist, @subplaylist) %></p>Here is where the movies forum parameters are
<%= form_for([@subplaylist, @movie], :html=>{:multipart => true}) do |f| %>
<% if @movie.errors.any? %>
<div>
<h2><%= pluralize(@movie.errors.count, "error") %> prohibited this movie from being saved:</h2>
<ul>
<% @movie.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<br />
<div class="pagetext">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="pagetext">
<%= f.file_field :video %>
</div>
<div class="pagetext">
<%= f.label :remote_video_url, "or video URL" %><br />
<%= f.text_field :remote_video_url %>
</div>
<div class="pagetext">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="pagetext">
<%= f.submit %>
</div>
<br />
<% end %>Here is the movies helper code
module MoviesHelper
def mode(type)
code = auto_logout
if(code == true)
sign_out
redirect_to root_path
else
#Check if Maintenance is turned_on
allmode = Maintenancemode.find_by_id(1)
moviemode = Maintenancemode.find_by_id(19)
mode_turned_on = (allmode.maintenance_on || moviemode.maintenance_on)
#Determine if any maintenance is on
if(mode_turned_on)
#Determine if we are a regular user
regularUser = (!current_user || !current_user.admin?)
if(regularUser)
#Determine which maintenance mode is on
if(allmode.maintenance_on)
redirect_to maintenance_path
else
redirect_to movies_maintenance_path
end
else
switch type
end
else
switch type
end
end
end
private
def getType(user)
if(user.admin)
value = "$"
else
typeFound = Usertype.find_by_user_id(user.id)
if(typeFound)
type = typeFound.privilege
if(type == "Reviewer")
value = "^"
elsif(type == "Banned")
value = "!"
else
value = "~"
end
else
value = "~"
end
end
return value
end
def movieApproved
movieFound = Movie.find_by_id(params[:movie_id])
if(movieFound)
movieFound.reviewed = true
pouch = Pouch.find_by_user_id(movieFound.user_id)
pointsForMovie = 10
pouch.amount += pointsForMovie
@pouch = pouch
@pouch.save
@movie = movieFound
@movie.save
# MovieMailer.movie_approved(@movie, pointsForMovie).deliver
redirect_to movies_review_path
else
render "public/404"
end
end
def movieDenied
movieFound = Movie.find_by_id(params[:movie_id])
if(movieFound)
#Retrieve the user who owns this pet first
#userEmail = petFound.user.email
#Send mail to user with link to edit the pet they sent
@movie = movieFound
MovieMailer.movie_denied(@movie).deliver
redirect_to movies_review_path
else
render "public/404"
end
end
def createMovie(subplaylistFound)
newMovie = subplaylistFound.movies.new
@subplaylist = subplaylistFound
@movie = newMovie
end
def saveMovie(subplaylistFound, logged_in)
newMovie = subplaylistFound.movies.new(params[:movie])
newMovie.user_id = logged_in.id
currentTime = Time.now
newMovie.created_on = currentTime
@movie = newMovie
if(@movie.save)
@subplaylist = subplaylistFound
# MovieMailer.review_movie(@movie).deliver
flash[:success] = "#{@movie.title} is currently being reviewed please check back later."
redirect_to subplaylist_movie_path(@subplaylist, @movie)
else
render "new"
end
end
def switch(type)
if(type == "index") #Admin only
logged_in = current_user
if(logged_in)
if(logged_in.admin)
allMovies = Movies.order("created_on desc").page(params[:page]).per(10)
@movies = allMovies
else
redirect_to root_path
end
else
redirect_to root_path
end
elsif(type == "show")
movieFound = Movie.find_by_id(params[:id])
if(movieFound)
subplaylistFound = Subplaylist.find_by_id(params[:subplaylist_id])
if(subplaylistFound)
if(movieFound.reviewed)
@subplaylist = subplaylistFound
@movie = movieFound
else
logged_in = current_user
if(logged_in)
userMatch = ((logged_in.id == movieFound.user_id) || logged_in.admin)
if(userMatch)
@subplaylist = subplaylistFound
@movie = movieFound
else
redirect_to root_path
end
else
redirect_to root_path
end
end
else
redirect_to root_path
end
else
render "public/404"
end
elsif(type == "new")
logged_in = current_user
if(logged_in)
subplaylistFound = Subplaylist.find_by_id(params[:subplaylist_id])
if(subplaylistFound)
if(subplaylistFound.collab_mode)
createMovie(subplaylistFound)
else
userMatch = (logged_in.id == subplaylistFound.user_id)
if(userMatch)
createMovie(subplaylistFound)
else
redirect_to root_path
end
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "create")
logged_in = current_user
if(logged_in)
subplaylistFound = Subplaylist.find_by_id(params[:subplaylist_id])
if(subplaylistFound)
if(subplaylistFound.collab_mode)
saveMovie(subplaylistFound, logged_in)
else
userMatch = (logged_in.id == subplaylistFound.user_id)
if(userMatch)
saveMovie(subplaylistFound, logged_in)
else
redirect_to root_path
end
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "edit")
logged_in = current_user
if(logged_in)
movieFound = Movie.find_by_id(params[:id])
if(movieFound)
userMatch = (logged_in.id == movieFound.user_id)
if(userMatch)
subplaylistFound = Subplaylist.find_by_id(movieFound.subplaylist_id)
if(subplaylistFound)
@subplaylist = subplaylistFound
@movie = movieFound
else
render "public/404"
end
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "update")
logged_in = current_user
if(logged_in)
movieFound = Movie.find_by_id(params[:id])
if(movieFound)
userMatch = (logged_in.id == movieFound.user_id)
if(userMatch)
subplaylistFound = Subplaylist.find_by_id(movieFound.subplaylist_id)
if(subplaylistFound)
@movie = movieFound
if(@movie.update_attributes(params[:movie]))
@subplaylist = subplaylistFound
flash[:success] = 'Movie was successfully updated.'
redirect_to subplaylist_movie_path(@subplaylist, @movie)
else
render "edit"
end
else
render "public/404"
end
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "destroy")
logged_in = current_user
if(logged_in)
movieFound = Movie.find_by_id(params[:id]) #Need to move this below the admin section to protect it
if(movieFound)
if(logged_in.admin)
subplaylistFound = Subplaylist.find_by_id(movieFound.subplaylist_id)
if(subplaylistFound)
@movie = movieFound
@subplaylist = subplaylistFound
@movie.destroy
redirect_to mainplaylist_subplaylist_path(@subplaylist.mainplaylist, @subplaylist)
else
render "public/404"
end
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "review") #Admin
logged_in = current_user
if(logged_in)
if(logged_in.admin)
allMovies = Movie.all
moviesToReview = allMovies.select{|movie| !movie.reviewed}
@movies = Kaminari.paginate_array(moviesToReview).page(params[:page]).per(10)
else
typeFound = Usertype.find_by_user_id(logged_in.id)
if(typeFound.privilege == "Reviewer")
allMovies = Movie.all
moviesToReview = allMovies.select{|movie| !movie.reviewed}
@movies = Kaminari.paginate_array(moviesToReview).page(params[:page]).per(10)
else
redirect_to root_path
end
end
else
redirect_to root_path
end
elsif(type == "approve") #Admin
logged_in = current_user
if(logged_in)
if(logged_in.admin)
movieApproved
else
typeFound = Usertype.find_by_user_id(logged_in.id)
if(typeFound.privilege == "Reviewer")
movieApproved
else
redirect_to root_path
end
end
else
redirect_to root_path
end
elsif(type == "deny") #Admin
logged_in = current_user
if(logged_in)
if(logged_in.admin)
movieDenied
else
typeFound = Usertype.find_by_user_id(logged_in.id)
if(typeFound.privilege == "Reviewer")
movieDenied
else
redirect_to root_path
end
end
else
redirect_to root_path
end
end
end
endHere is the subplaylists show code
<% provide(:title, "Subplaylist: The place where users videos gets uploaded to!") %>
<% provide(:keywords, "user, video, uploaded") %>
<% provide(:description, "Allows the categorization of various videos that the user submitted successfully.") %>
<p><%= notice %></p>
<h1 class="pageheader"><%= @subplaylist.title %></h1>
<br />
<p class="pagetext"><%= @subplaylist.description %></p>
<br />
<div class="pagebox"><%= paginate @movies %></div>
<br />
<div class="pagetext">
<% @movies.each_with_index do |movie, index| %>
<div class="container">
<div class="inner">
<div class="inner"><%= link_to movie.title, subplaylist_movie_path(@subplaylist, movie) %></div>
<% if current_user && (current_user.id == movie.user_id || current_user.admin? )%>
<div class="inner"><%= button_to 'Edit', edit_subplaylist_movie_path(@subplaylist, movie), method: :get %></div>
<div class="inner"><%= button_to 'Destroy', [@subplaylist, movie], method: :delete, data: { confirm: 'Are you sure?' } %></div>
<% end %>
<p><%= video_tag movie.video_url(:thumb).to_s, controls: true %></p>
</div>
<br />
<p>Created on: <%= movie.created_on.strftime("%B-%d-%Y") %></p>
<p>Owner: <%= getType(movie.user) %><%= link_to movie.user.vname, user_path(movie.user) %></p>
</div>
<% if ((index + 1) % 3) == 0 %>
<br />
<br />
<% end %>
<% end %>
</div>
<br />
<% if current_user %>
<p class="pagetext"><%= link_to "New Movie", new_subplaylist_movie_path(@subplaylist) %></p>
<br />
<% end %>
<p class="pagetext"><%= link_to 'Back', user_mainplaylist_path(@mainplaylist.user.vname, @subplaylist.mainplaylist.title) %></p>Here is the subplaylists model
class Subplaylist < ActiveRecord::Base
attr_accessible :title, :description, :collab_mode
belongs_to :user
belongs_to :mainplaylist
has_many :movies, :foreign_key => "subplaylist_id", :dependent => :destroy
VALID_NAME = /\A[A-Za-z][A-Za-z1-9][A-Za-z1-9 ]+\z/
validates :title, presence: true, format: {with: VALID_NAME}
validates :description, presence: true
endHere is the subplaylists controller code
class SubplaylistsController < ApplicationController
include SubplaylistsHelper
def index
mode "index"
end
def show
mode "show"
end
def new
mode "new"
end
def edit
mode "edit"
end
def create
mode "create"
end
def update
mode "update"
end
def destroy
mode "destroy"
end
endHere is the subplaylist helper code
module SubplaylistsHelper
def mode(type)
code = auto_logout
if(code == true)
sign_out
redirect_to root_path
else
#Check if Maintenance is turned_on
allmode = Maintenancemode.find_by_id(1)
subplaylistmode = Maintenancemode.find_by_id(18)
mode_turned_on = (allmode.maintenance_on || subplaylistmode.maintenance_on)
#Determine if any maintenance is on
if(mode_turned_on)
#Determine if we are a regular user
regularUser = (!current_user || !current_user.admin?)
if(regularUser)
#Determine which maintenance mode is on
if(allmode.maintenance_on)
redirect_to maintenance_path
else
redirect_to subplaylists_maintenance_path
end
else
switch type
end
else
switch type
end
end
end
private
def getType(user)
if(user.admin)
value = "$"
else
typeFound = Usertype.find_by_user_id(user.id)
if(typeFound)
type = typeFound.privilege
if(type == "Reviewer")
value = "^"
elsif(type == "Banned")
value = "!"
else
value = "~"
end
else
value = "~"
end
end
return value
end
def switch(type)
if(type == "show")
subplaylistFound = Subplaylist.find_by_id(params[:id])
if(subplaylistFound)
mainplaylistFound = Mainplaylist.find_by_title(params[:mainplaylist_id])
if(mainplaylistFound)
playlistMatch = (subplaylistFound.mainplaylist_id == mainplaylistFound.id)
if(playlistMatch)
@mainplaylist = mainplaylistFound
@subplaylist = subplaylistFound
subplaylistMovies = @subplaylist.movies.all
reviewedMovies = subplaylistMovies
if(subplaylistMovies.count > 0)
reviewedMovies = subplaylistMovies.select{|movie| movie.reviewed}
end
@movies = Kaminari.paginate_array(reviewedMovies).page(params[:page]).per(10)
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "destroy")
logged_in = current_user
if(logged_in)
subplaylistFound = Subplaylist.find_by_id(params[:id]) #Need to move this below the admin section to protect it
if(subplaylistFound)
if(logged_in.admin)
mainplaylistFound = Mainplaylist.find_by_id(subplaylistFound.mainplaylist_id)
if(mainplaylistFound)
@subplaylist = subplaylistFound
@mainplaylist = mainplaylistFound
@subplaylist.destroy
redirect_to mainplaylist_subplaylists_path(@mainplaylist)
else
render "public/404"
end
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
end
end
endHere is the User model
class User < ActiveRecord::Base
attr_accessible :email, :first_name, :last_name, :login_id, :vname, :password, :password_confirmation, :avatar
has_secure_password
mount_uploader :avatar, AvatarUploader
before_save { |user| user.email = user.email.downcase }
before_save { |user| user.first_name = user.first_name.humanize }
#key
has_one :sessionkey, :foreign_key => "user_id", :dependent => :destroy
has_one :usertype, :foreign_key => "user_id", :dependent => :destroy
#Video section
has_many :mainplaylists, :foreign_key => "user_id", :dependent => :destroy
has_many :subplaylists, :foreign_key => "user_id", :dependent => :destroy
has_many :movies, :foreign_key => "user_id", :dependent => :destroy
#validates :first_name, presence: true
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
VALID_NAME_REGEX = /\A[a-z][a-z][a-z]+\z/i
VALID_VNAME_REGEX = /\A[A-Za-z][A-Za-z][A-Za-z][A-Za-z0-9 ]+([-][A-Za-z0-9 ]+)?\z/
VALID_PASSWORD_REGEX = /\A[A-Za-z0-9!][A-Za-z0-9!][A-Za-z0-9!][A-Za-z0-9!][A-Za-z0-9!][A-Za-z0-9!]+\z/
validates :first_name, presence: true, format: { with: VALID_NAME_REGEX}
validates :last_name, presence: true, format: { with: VALID_NAME_REGEX}
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX}
validates :login_id, presence: true, format: { with: VALID_VNAME_REGEX}, uniqueness: { case_sensitive: false}
validates :vname, presence: true, format: { with: VALID_VNAME_REGEX}, uniqueness: { case_sensitive: false}
validates :password, length: {minimum: 6}#, format: { with: VALID_PASSWORD_REGEX}
validates :password_confirmation, presence: true #, format: { with: VALID_PASSWORD_REGEX}
def to_param
vname
end
endHere is the sessionkey model
class Sessionkey < ActiveRecord::Base
belongs_to :user
endHere is the usertype model
class Usertype < ActiveRecord::Base
attr_accessible :privilege, :user_id #Only priviledge will be changeable
belongs_to :user
endError message
No such file or directory - ffmpeg -i /home/eric/Projects/Local/Lduelingpets/Trial/public/uploads/tmp/1466811951-3149-2702/mp4_TrialMovies.mp4
-
The neutering of Google Code-In 2011
Posting this from the Google Summer of Code Mentor Summit, at a session about Google Code-In !
Google Code-In is the most innovative open-source program I’ve ever seen. It provided a way for students who had never done open source — or never even done programming — to get involved in open source work. It made it easy for people who weren’t sure of their ability, who didn’t know whether they could do open source, to get involved and realize that yes, they too could do amazing work — whether code useful to millions of people, documentation to make the code useful, translations to make it accessible, and more. Hundreds of students had a great experience, learned new things, and many stayed around in open source projects afterwards because they enjoyed it so much !
x264 benefitted greatly from Google Code-In. Most of the high bit depth assembly code was written through GCI — literally man-weeks of work by an professional developer, done by high-schoolers who had never written assembly before ! Furthermore, we got loads of bugs fixed in ffmpeg/libav, a regression test tool, and more. And best of all, we gained a new developer : Daniel Kang, who is now a student at MIT, an x264 and libav developer, and has gotten paid work applying the skills he learned in Google Code-In !
Some students in GCI complained about the system being “unfair”. Task difficulties were inconsistent and there were many ways to game the system to get lots of points. Some people complained about Daniel — he was completing a staggering number of tasks, so they must be too easy. Yet many of the other students considered these tasks too hard. I mean, I’m asking high school students to write hundreds of lines of complicated assembly code in one of the world’s most complicated instruction sets, and optimize it to meet extremely strict code-review standards ! Of course, there may have been valid complaints about other projects : I did hear from many students talking about gaming the system and finding the easiest, most “profitable” tasks. Though, with the payout capped at $500, the only prize for gaming the system is a high rank on the points list.
According to people at the session, in an effort to make GCI more “fair”, Google has decided to change the system. There are two big changes they’re making.
Firstly, Google is requiring projects to submit tasks on only two dates : the start, and the halfway point. But in Google Code-In, we certainly had no idea at the start what types of tasks would be the most popular — or new ideas that came up over time. Often students would come up with ideas for tasks, which we could then add ! A waterfall-style plan-everything-in-advance model does not work for real-world coding. The halfway point addition may solve this somewhat, but this is still going to dramatically reduce the number of ideas that can be proposed as tasks.
Secondly, Google is requiring projects to submit at least 5 tasks of each category just to apply. Quality assurance, translation, documentation, coding, outreach, training, user interface, and research. For large projects like Gnome, this is easy : they can certainly come up with 5 for each on such a large, general project. But often for a small, focused project, some of these are completely irrelevant. This rules out a huge number of smaller projects that just don’t have relevant work in all these categories. x264 may be saved here : as we work under the Videolan umbrella, we’ll likely be able to fudge enough tasks from Videolan to cover the gaps. But for hundreds of other organizations, they are going to be out of luck. It would make more sense to require, say, 5 out of 8 of the categories, to allow some flexibility, while still encouraging interesting non-coding tasks.
For example, what’s “user interface” for a software library with a stable API, say, a libc ? Can you make 5 tasks out of it that are actually useful ?
If x264 applied on its own, could you come up with 5 real, meaningful tasks in each category for it ? It might be possible, but it’d require a lot of stretching.
How many smaller or more-focused projects do you think are going to give up and not apply because of this ?
Is GCI supposed to be something for everyone, or just or Gnome, KDE, and other megaprojects ?
-
How to optimize ffmpeg w/ x264 for multiple bitrate output files
10 octobre 2013, par JonesyThe goal is to create multiple output files that differ only in bitrate from a single source file. The solutions for this that were documented worked, but had inefficiencies. The solution that I discovered to be most efficient was not documented anywhere that I could see. I am posting it here for review and asking if others know of additional optimizations that can be made.
Source file MPEG-2 Video (Letterboxed) 1920x1080 @>10Mbps
MPEG-1 Audio @ 384Kbps
Destiation files H264 Video 720x400 @ multiple bitrates
AAC Audio @ 128Kbps
Machine Multi-core ProcessorThe video quality at each bitrate is important so we are running in 2-Pass mode with the 'medium' preset
VIDEO_OPTIONS_P2 = -vcodec libx264 -preset medium -profile:v main -g 72 -keyint_min 24 -vf scale=720:-1,crop=720:400
The first approach was to encode them all in parallel processes
ffmpeg -y -i $INPUT_FILE $AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 250k -threads auto -f mp4 out-250.mp4 & ffmpeg -y -i $INPUT_FILE $AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 500k -threads auto -f mp4 out-500.mp4 & ffmpeg -y -i $INPUT_FILE $AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 700k -threads auto -f mp4 out-700.mp4 &
The obvious inefficiencies are that the source file is read, decoded, scaled, and cropped identically for each process. How can we do this once and then feed the encoders with the result ?
The hope was that generating all the encodes in a single ffmpeg command would optimize-out the duplicate steps.
ffmpeg -y -i $INPUT_FILE \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 250k -threads auto -f mp4 out-250.mp4 \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 500k -threads auto -f mp4 out-500.mp4 \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 700k -threads auto -f mp4 out-700.mp4However, the encoding time was nearly identical to the previous multi-process approach. This leads me to believe that all the steps are again being performed in duplicate.
To force ffmpeg to read, decode, and scale only once, I put those steps in one ffmpeg process and piped the result into another ffmpeg process that performed the encoding. This improved the overall processing time by 15%-20%.
INPUT_STREAM="ffmpeg -i $INPUT_FILE -vf scale=720:-1,crop=720:400 -threads auto -f yuv4mpegpipe -"
$INPUT_STREAM | ffmpeg -y -f yuv4mpegpipe -i - \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 250k -threads auto out-250.mp4 \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 500k -threads auto out-500.mp4 \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 700k -threads auto out-700.mp4Does anyone see potential problems with doing it this way, or know of a better method ?