Ruby library for mashing up video, images and audio utilizing FFmpeg and Ecasound
Use moviemasher.rb to encode mashups of video, audio, and images together with titles and other visual effects. Each transcoding
job specifies multiple media
inputs to be encoded together into one or more
outputs, as well as metadata like where to find source assets and where to put the final rendering.
- join files together sequentially with trimming and transitions
- mix audio tracks together with variable fading and looping
- composite visual tracks together with transformations and chromakey
- add titling with your own fonts overtop other elements translucently
- transfer media files to and from remote hosts using authentication
- specify callbacks that alert your system of processing milestones
Overview: FFMpeg + Mash = Transcoder
The project aims to simplify common audio/video editing operations by turning your job into a series of shell commands, and then overseeing their execution. As part of job processing, media inputs can be downloaded from remote hosts and rendered outputs can be uploaded as well. Using the same request mechanisms, external systems can be alerted by callbacks triggered when a job is started, during its processing and/or when it's completed.
In addition to the raw media assets (video, audio and images), jobs can contain mash inputs that describe more complex compositing, titling and other effects. The related moviemasher.js project can be used to generate and display JSON formatted mash descriptions within a web browser, and angular-moviemasher can be used to package these into job descriptions.
Jobs are provided to the system for processing in different ways, depending on how it's been configured and deployed. At the lowest level, the MovieMasher.process method is sent a job as a hash, a JSON/YAML formatted string or a local path to one. The MovieMasher.process_queues method calls it with any jobs it finds while scanning a preconfigured watch folder or queue. This scanning can be done for a certain number of seconds, until no jobs are found, just once or forever. There are rake tasks for each of these methods, to simplify calling from shell scripts, cron jobs and other tasks.
- An S3 bucket can be a source for inputs or a destination for outputs
- An SQS queue can be polled and messages processed as jobs
- An access key id/secret can be passed to AWS.config for authentication
- Alternatively, environmental variables or an EC2 role can authenticate
Additionally, the Movie Masher AMI is launchable with OneClick in Marketplace as a deployment of all related projects and supporting applications. It includes an upstart task that executes
rake moviemasher:init to merge any User Data supplied in JSON format into the configuration plus a cron job that continually executes
rake moviemasher:process_queues, so it's possible to run in a headless mode polling an SQS queue for jobs. Without User Data, the instance will start up Apache and serve the angular-moviemasher project for demonstration - the instance id acts as a shared password.
moviemasher/moviemasher.rb image is automatically built from the official
ruby image, adding builds of FFmpeg, Ecasound and supporting audio/visual applications and libraries. It can be used to process jobs supplied directly on the command line, or to grab them from a directory/queue - either approach supports running in interactive or daemon mode. The Dockerfile contains a VOLUME instruction for each directory it works with, including queue_directory so that job files residing on the host can be easily processed.
To display documentation of configuration options:
docker run -it --rm moviemasher/moviemasher.rb moviemasher --help
To process jobs formatted in JSON/YAML or paths to them directly from the command line:
docker run -it --rm moviemasher/moviemasher.rb process "JOB" "JOB"
To process all JSON or YAML formatted jobs in directory 'my_jobs' residing on the host:
docker run -it --rm -v my_jobs:/tmp/moviemasher/queue moviemasher/moviemasher.rb
To continually process jobs from container's queue volume:
docker run -d -t --name=moviemasher moviemasher/moviemasher.rb process_loop
t switch - it's required for Ecasound to function properly. You'll need to subsequently execute
docker stop moviemasher and
docker rm moviemasher to stop processing and remove the container created.
To process a single job from an SQS queue:
docker run -it --rm moviemasher/moviemasher.rb process_one --queue_url=[URL] --aws_access_key_id=[ID] --aws_secret_access_key=[SECRET]
URL points to an existing SQS Queue that provides read/write access to the owner of the access key with ID and SECRET. Messages can be in JSON or YAML format. This example demonstrates overriding the configuration with command line arguments - all commands support this. The MOVIEMASHER_CONFIG environmental variable can also be set to a configuration file residing on the container in JSON/YAML format, though arguments take precedence.
When processing jobs in a directory or queue, the process_seconds configuration option ultimately controls how long polling continues and therefore how long the container runs. The following values are supported:
- [N]: poll for N seconds, then exit
- 0: do not poll, just exit
- -1: process a single job if found, then exit
- -2: poll until no jobs remain, then exit
- -3: poll until container stopped
The Dockerfile specifies an ENTRYPOINT that provides several convenience commands, but calls exec with any it doesn't recognize so that containers behave as expected. The following commands are supported:
- moviemasher (default): call MovieMasher.process_queues
- process_one: call MovieMasher.process_queues with process_seconds=-1
- process_all: call MovieMasher.process_queues with process_seconds=-2
- process_loop: call MovieMasher.process_queues with process_seconds=-3
- process: call MovieMasher.process for each supplied argument
Tested in Ruby 1.9.3 and 2.1.5 (the
ruby docker images) and on multiple UNIX flavors including OSX. Suggested audio/video libraries are only needed if you're decoding or encoding in their formats. Likewise, the aws-sdk gem is only needed when utilizing Amazon's services.
- Applications: FFmpeg, Ecasound, Sox
- Ruby Gems: aws-sdk, builder, mime-types, multipart-post, require_all, uuid
- Audio Libraries: mp3lame, ogg, opencore, samplerate, sndfile, speex, theora, vorbis
- Video Libraries: dirac, fontconfig, frei0r, fribidi, gd, openjpeg, vpx, xvidcore, x264
How to Install
Transcoding audio and video is extremely processor intensive, so while installation might be possible on most machines it isn't reccommended for all environments. In particular, running alongside a web server is only practical for demonstration purposes. Typically in production a pool of machines is deployed with each instance running a single process solely engaged in transcoding.
- Review Dockerfile for commands that work on the
- Install av libraries for supported formats and codecs
- Install sox, ecasound and ffmpeg applications (in that order)
- Install ruby and bundler gem
To install required gems
cdto project directory and execute:
Edit config/config.yml configuration file to match paths on system and configure logging/debugging options
To scan watch folder and/or queue for jobs
cdto project directory and execute:
optionally add crontab entry from config/aws/moviemasher.cron, after checking its binary paths
If any problems arise while utilizing this repository, a GitHub Issue Ticket should be filed. Please include the job description that's causing problems and any relevant log entries - issues with callbacks can typically be resolved faster after seeing entries from the receiving web server's log. Please post your issue ticket in the appropriate repository and refrain from cross posting - all projects are monitored with equal zeal.
Please join in the shareable economy by gifting your efforts towards improving this project in any way you feel inclined. Pull requests for fixes, features and refactorings are always appreciated, as are documentation updates. Creative help with graphics, video and the web site is also needed. Please contact through MovieMasher.com to discuss your ideas.
Docker is used extensively to develop this project. Additionally, the spec tests rely on the other two Movie Masher projects and the clientside_aws project which should all be pulled into the same directory that contains this repository:
To run spec tests utilizing options from
docker-compose -f config/docker/test/test.yml run --rm rspec
All files generated by tests appear in
tmp/spec sub directories. Each job has its own log file in
To run rubocop with options from
docker-compose -f config/docker/rubocop/rubocop.yml run --rm rubocop
To rebuild Gemfile.lock from Gemfile:
docker-compose -f config/docker/bundler/bundler.yml run --rm bundler
To have rdoc rebuild documentation in
docs from source code:
rdoc --visibility=public -o doc --main='Documentation.md' --fmt=darkfish --markup=tomdoc --tab-width=2 --no-dcov --exclude='/spec' --exclude='/log' --exclude='/Gemfile' --exclude='/tmp' --exclude='/config' --exclude='/index.rb' --exclude='/doc' --exclude='/bin' --exclude='/Rakefile' --exclude='/Docker' --exclude='/README-short' --exclude='/LICENSE'
Known issues in this version
- local/sqs import/export has not been thoroughly tested
- archiving of outputs not yet supported
- freeze frame not yet supported
- audio still being done in Ecasound
- audio spec tests not yet generating files from scratch
Migrating from Version 4.0.7
lengthkey in clips has been renamed
videokeys in mash tracks have been moved to mash.
trackskey in mashes has been removed.
fpskey in outputs has been renamed
audio_frequencykey in outputs has been renamed
trimkey in inputs has been renamed
- The new
mashkey in mash inputs should be used for embedded mashes
sourcekey in mash inputs should only contain a source object