Category Archives: Application

Creating a video montage with ffmpeg

With 1080p (and in some cases 2K) cameras now being standard on mobile phones, it’s easier than ever to create high quality video. Granted, the lack of quality free video editors on Windows / Linux leaves something to be desired.

I played with Blender VSE (Video Sequence Editor) to try and create a montage of my most recent motorcycle rides but the interface was non-intuitive and had a rather high learning curve.

So, I turned to the venerable ffmpeg to create my video montage.

Selecting the source content
Before jumping to the command line, you will need to gather the list of clips you want to join and have a basic idea of what you want to achieve. Using your favourite video player (VideoLAN Player, in my case), play through your captured videos and find the timeframe for trimming.

For the purposes of this tutorial, let’s assume this is my game plan:


Video effect 1: fade in from black
Audio track 1: filename "audio.mp3"
Video clip 1: filename "getting_ready.mov"; length 03:30 [mm:ss]; trim start 01:30; trim end 02:15
Text overlay 1: text "Touch Sensitive - Pizza Guy"; background partially transparent; font Arial; position lower left
Video effect 2: Cross fade
Video clip 2, filename "riding_fast.mov", length 00:50 [mm:ss], trim start 00:15, trim end 00:50
Video effect 3: Cross fade
Video clip 3, filename "going_home.mov", length 02:00 [mm:ss], trim start 00:45, trim end 01:55

Understanding ffmpeg
The ffmpeg documentation is extensive and well written. I highly recommend you spend some time familiarising yourself with the video filter section.

Let’s begin by understanding the file formats of our videos. For this tutorial, since they are all recorded by the same camera they will all share the same video / audio codecs and container.

$ ffmpeg -i getting_ready.mp4
Guessed Channel Layout for Input Stream #0.1 : mono
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '.\getting_ready.mov':
  Metadata:
    major_brand     : qt
    minor_version   : 0
    compatible_brands: qt
    creation_time   : 2016-01-01 00:34:11
    original_format : NVT-IM
    original_format-eng: NVT-IM
    comment         : CarDV-TURNKEY
    comment-eng     : CarDV-TURNKEY
  Duration: 00:3:30.47, start: 0.000000, bitrate: 16150 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 14965 kb/s, 30 fps, 30 tbr, 30k tbn, 60k tbc (default)
    Metadata:
      creation_time   : 2016-01-01 00:34:11
      handler_name    : DataHandler
      encoder         : h264
    Stream #0:1(eng): Audio: pcm_s16le (sowt / 0x74776F73), 32000 Hz, 1 channels, s16, 512 kb/s (default)
    Metadata:
      creation_time   : 2016-01-01 00:34:11
      handler_name    : DataHandler

Important items to note

  • In “Stream #0:0” information, the video encoding is H.264. We will keep this codec.
  • In “Stream #0:1” information, we can see that the audio is raw audio (16 bits per sample, little endian). We will be converting this to AAC in the output.

Trimming the clips
We will begin the effects by trimming the portions we need. As we will be adding effects later, we’ll leave 2 seconds on either side of the trim.


$ ffmpeg -i ./getting_ready.mov -ss 00:01:30.0 -c copy -t 00:00:47.0 ./output-1.mov
$ ffmpeg -i ./riding_fast.mov -ss 00:00:13.0 -c copy -t 00:00:39.0 ./output-2.mov
$ ffmpeg -i ./going_home.mov -ss 00:00:43.0 -c copy -t 00:01:12.0 ./output-3.mov

Applying effects
Note: If you want to speed up processing time while you get the hang of this, you can scale the videos down and then apply the effects to the full size video once you’re satisified with the output.
$ ffmpeg -i ./output-1.mov -vf scale=320:-1 ./output-1s.mov
-1 on the scale filter means determine the height based on the aspect ratio of the input file.

First, I’ll show how to add the effects individually (at a potential loss of quality). Then we will follow up by chaining the filters together.

Let us apply the fade in/outs to the videos.


$ ffmpeg -i ./output-1s.mov -vf fade=t=out:st=45.0:d=2.0 ./output-1sf.mov
$ ffmpeg -i ./output-2s.mov -vf 'fade=in:st=0.0:d=2.0, fade=t=out:st=37.0:d=2.0' ./output-2sf.mov
$ ffmpeg -i ./output-3s.mov -vf fade=in:st=0.0:d=2.0 ./output-3sf.mov

Unfortunately, as H.264 does not support alpha transparency, we will need to use the filtergraph to let us apply alpha (for the fading) to the stream before outputting to the final video. First, let’s rebuild the above command as a filter graph.

$ ffmpeg -i ./output-1s.mov -i ./output-2s.mov -i ./output-3s.mov -filter_complex '[0:v]fade=t=out:st=45.0:d=2.0[out1];[1:v]fade=in:st=0.0:d=2.0, fade=t=out:st=37.0:d=2.0[out2];[2:v]fade=in:st=0.0:d=2.0[out3]' -map '[out1]' ./output-1sf.mov -map '[out2]' ./output-2sf.mov -map '[out3]' ./output-3sf.mov

This uses the filter_complex option to enable a filtergraph. First, we list the inputs. Each input is handled in order and can be access by the [n:v] operator where ‘n’ is the input number (starting from 0) and ‘v’ means access the video stream. As you can tell the audio was not copied from the input streams in this command. Semicolon is used to separated parallel operations and the comma separates linear operations (operating upon the same stream).

Next, let’s add the alpha effect and combine the videos into one output.

$ ffmpeg -i ./output-1s.mov -i ./output-2s.mov -i ./output-3s.mov -filter_complex '[0:v]fade=t=out:st=45.0:d=2.0:alpha=1[out1];[1:v]fade=in:st=0.0:d=2.0:alpha=1, fade=t=out:st=37.0:d=2.0:alpha=1[out2];[2:v]fade=in:st=0.0:d=2.0:alpha=1[out3];[out2][out1]overlay[out4];[out3][out4]overlay[out5]' -map [out5] out.mov

Next add the text overlay.

$ ffmpeg -i ./output-1s.mov -i ./output-2s.mov -i ./output-3s.mov -filter_complex "[0:v]fade=t=out:st=45.0:d=2.0:alpha=1[out1];[1:v]fade=in:st=0.0:d=2.0:alpha=1, fade=t=out:st=37.0:d=2.0:alpha=1[out2];[2:v]fade=in:st=0.0:d=2.0:alpha=1[out3];[out2][out1]overlay[out4];[out3][out4]overlay[out5];[out5]drawtext=fontfile=/Windows/Fonts/Arial.ttf:text='Touch Sensitive - Pizza Guy':fontcolor=white:x=(0.08*w):y=(0.8*h)" out.mov

Finally, let’s have the text appear at 5 seconds and dissappear at 10 seconds.


$ ffmpeg -i ./output-1s.mov -i ./output-2s.mov -i ./output-3s.mov -filter_complex "[0:v]fade=t=out:st=45.0:d=2.0:alpha=1[out1];[1:v]fade=in:st=0.0:d=2.0:alpha=1, fade=t=out:st=37.0:d=2.0:alpha=1[out2];[2:v]fade=in:st=0.0:d=2.0:alpha=1[out3];[out2][out1]overlay[out4];[out3][out4]overlay[out5];[out5]drawtext=fontfile=/Windows/Fonts/Arial.ttf:text='Touch Sensitive - Pizza Guy':x=(0.08*w):y=(0.8*h):fontcolor_expr=ffffff%{eif\\:clip(255*(between(t\,5\,10))\,0\,255)\\:x\\:2}" out.mov

At last, let’s add the audio track and fade it out.

$ ffmpeg -i ./output-1s.mov -i ./output-2s.mov -i ./output-3s.mov -i ./audio.aac -filter_complex "[0:v]fade=t=out:st=45.0:d=2.0:alpha=1[out1];[1:v]fade=in:st=0.0:d=2.0:alpha=0, fade=t=out:st=37.0:d=2.0:alpha=1[out2];[2:v]fade=in:st=0.0:d=2.0:alpha=0[out3];[out1][out2]overlay[out4];[out3][out4]overlay[out5];[out5]drawtext=fontfile=/Windows/Fonts/Arial.ttf:text='Touch Sensitive - Pizza Guy':x=(0.08*w):y=(0.8*h):fontcolor_expr=ffffff%{eif\\:clip(255*(between(t\,5\,10))\,0\,255)\\:x\\:2}" -shortest -map 3:0 -af afade=t=out:st=68:d=4 out.mov

The final command, all together.  More information about PTS-STARTPTS can be found here.

 

ffmpeg -y -i ./output-1.mov -i ./output-2.mov -i ./output-3.mov -i ./audio.aac -filter_complex "[0:v]fade=t=out:st=10.0:d=2.0:alpha=1,setpts=PTS-STARTPTS[out1];
 [1:v]fade=in:st=0.0:d=2.0:alpha=1,fade=t=out:st=26.0:d=2.0:alpha=1,setpts=PTS-STARTPTS+(10/TB)[out2];
 [2:v]fade=in:st=0.0:d=2.0:alpha=1,fade=t=out:st=16.0:d=4.0:alpha=0,setpts=PTS-STARTPTS+(36/TB)[out3];
 [out1][out2]overlay[out4];
 [out4][out3]overlay[out5];[out5]drawtext=fontfile=/Windows/Fonts/Arial.ttf:text='Touch Sensitive - Pizza Guy':x=(0.08*w):y=(0.8*h):fontsize=52:fontcolor_expr=ffffff%{eif\\:clip(255*(between(t\,3\,8))\,0\,255)\\:x\\:2}" -map 3:0 -af afade=t=out:st=52:d=4 -shortest output.mov
Advertisements

Installing Windows XP in VirtualBox

Not too difficult, here are a few tips to make sure that your experience is flawless.

When configuring the virtual machine, make sure that you

  • enable APIC and ACPI in Settings –> System.
  • create a fixed sized harddisk to improve disk I/O speeds.

After installing Windows XP, make sure that you

  • download the driver for the Intel Pro 1000 network adapater and change the default adapter from PCNet to Intel Pro 1000 in Settings –> Network. For me, this improved network access speed and reduced DNS lookup delays.
  • install VirtualBox Guest Editions which enables seamless mouse integration and experimental Direct3D support by mounting the Guest Editions ISO.
  • if, in the event that Windows Update fails to work, register the Wups2.dll as outlined in the Microsoft Knowledge Base <http://support.microsoft.com/kb/943144&gt;

I extend my thanks to the VirtualBox team for making this so effortless. By the way, anything between 5G – 10G is a good size for your virtual harddisc.

Using your Gmail contacts in Mutt

I really enjoy using Mutt as my email client. However, sometimes I have to log
into my Gmail account to view my contacts. Tired of this, I exported my Gmail
contacts and imported them into abook.

Now I can view my Gmail contacts in Mutt.

Here’s how I did it:

(Sorry, no cut and paste instructions.)

* Export your Gmail contacts in the vcard format

* Download the abook source and patch it with the vcard diff (available on the abook website). NOTE: you can also use the vcard2abook.pl script available in the contrib/ dir in the source.

* Import your contacts by invoking abook with the following options: ‘–convert –informat vcard –infile INPUT.vcf –outformat abook –outfile ~/.abook/addressbook’

* Configure your abook (see `man abookrc`). abook has sane defaults so your config file can be very minimal:

set www_command=elinks
set add_email_prevent_duplicates=true

* Next, configure mutt to interact with abook. I added the following lines to my muttrc
set query_command=”abook –mutt-query ‘%s'”
macro index,pager A “abook –add-email-query” “add the sender to the address book”

That’s all :). Press A while in Mutt to add a contact and Q to query the address book.

Elinks advanced URI management

In the process of whipping elinks into a tame beast, I discovered several options that I wasn’t aware of.

URI rewriting: allows me to execute Google searches, dictionary lookups, and imdb queries within the ‘Goto URL’ dialog box. It should be enabled by default but if not, go to the Option manager -> Protocols -> URI rewriting and select either Dumb or Smart Prefixes. Once enabled, you can type ‘g search_term’ in the search box to quickly search Google for search_term. Look at the other prefixes to determine your options.

I wasn’t satisfied with having to use a prefix every time I wanted to search, so I modified the default template (Option manager -> Protocols -> URI rewriting -> Default template) to ‘http://www.google.com/search?q=%s&#8217;. This means that any entry in the ‘Goto URL’ dialog box that doesn’t look like a URL, a file, or an existing prefix will result in a Google search with that string!

Sessions: It turns out that elinks is a beast with many abilities, I wasn’t aware that it supported session saving/restoring (Option manager -> User interface -> Sessions).

URI passing: Often, when on the console, I’ll want to share a link with someone but I’ll be restricted by the atrocious lack of copy/paste. To solve the issue while using elinks, I enabled the link-external-command and tab-external-command options to save the highlighted link and current link, respectively, to a file.

To enable it, first go into the keybinding manager, toggle the display, and choose a keybinding for ‘main -> link-external-command’. This will be the keybinding you will press when you want to save the highlighted URL to a file. Likewise, choose a keybinding for ‘main -> tab-external-command.’ This is the keybinding you will press when you want to save the URL of the current tab to a file. After setting those shortcuts, go to ‘Option manager -> Document -> URI passing’ and create an entry with the contents ‘echo -n %c > ~/url’ (modify as you see fit). From now on, when you use (link|tab)-external-command the URL will be saved in ~/url.

For my inspiration, have a look at .

xf86-video-intel-2.6.3 and xorg-server-1.6.1 … a big fail

xf86-video-intel-2.6.3 — why do you cause so many problems? Ever since the transition from slow console switching (3 – 5 secs) to fast kernel mode switching (<< 1 sec) you insist on crashing when I kill X.org. Perhaps it's just me — perhaps I'm one of the unfortunate few that cannot have a perfect working system. NO, I do not want to compile X.org without KMS nor do I want to switch to the legacy intel video driver. *sigh*

I will find a fix but I'm afraid that the solution will be a X.org recompile.

Before you ask, xf86-video-intel-2.7.1 doesn't work at all, so I'll need to wait for a more stable release.

Changing the default X11 Cursor

Very trivial.

Unpack your cursor package to ~/.icons/.

The directory structure should be:

~/.icons
~/.icons/theme_name
~/.icons/theme_name/cursors

Create a symbolic link between ~/.icons/default and the theme_name and restart X.

ln -s ~/.icons/theme_name ~/.icons/default

If you have any issues, remove the symbolic link:

rm ~/.icons/default

create a ~/.icons/default directory

mkdir ~/.icons/default

and insert the following file (index.theme) into the ~/.icons/default directory:

touch ~/.icons/default/index.theme
vi ~/.icons/default/index.theme
   1 [Icon Theme]
   2 Inherit=theme_name

Done; easy.

Using xbindkeys to manage media buttons

More often that not, a keyboard will have extra functionality keys that you can bind to different operations.  Xbindkeys makes it easier to make each key perform a specific task.

First, run “xbindkeys -k” to determine the code for a key.  For example:

"Scheme Command"
m:0x0 + c:160
NoSymbol

Then change the “Scheme Command” section to the command that you want to run when the key is pressed.   For example:

"amixer set Master 5%+"
m:0x0 + c:176
NoSymbol

Place your newly created command in ~/.xbindkeysrc and add xbindkeys to your ~/.xinitrc.

MigrationHeuristic

An interesting discussion on the freedeskop mailing list revealed that setting MigrationHeuristic to “greedy” in the /etc/X11/xorg.conf may speed up Firefox when using the Intel (intel) drivers.
Read the discussion at http://lists.freedesktop.org/archives/xorg/2008-May/035451.html.

Setting up IMAP on Mutt

After receiving my HP 2710p, I decided to use IMAP instead of POP for
managing my email.  As you know, Mutt is my primary MUA (mail user agent).

The benefits of this setup are obvious: synchronous email (both on the computer
and on the webserver), space savings, and less programs to configure.

In this example, I’ll be setting up an IMAP connection to Gmail from Mutt.

First download the certificate of the organisation that is providing the IMAP
service.  Gmail uses “ThawtePremiumServerCA.crt”.  Make sure you compare your
checksum with the one provided by the Thawte Certificate Authority.  Place this
certificate in “~/.certs”.

Next, configure a profile for use with the IMAP connection.  I have an
engineering account with my university as well as a Gmail account, so I need two
profiles.  The Mutt profile is simple.

---~/.mutt/mutt1---
# email@gmail.com

source ~/.muttrc
set imap_user="email@gmail.com"
set folder="imaps://imap.gmail.com:993"
set spoolfile = "+INBOX"
set postponed=+"[Gmail]/Drafts"
set smtp_url="smtp://email@smtp.gmail.com:587/"
------

Note: My ~/.muttrc” contains global configuration values.

Next, simply add aliases for each profile that you create.  For example:

---~/.bashrc---
[ ... ]
alias mutt1="mutt -F ~/.mutt/muttrc_gmail"
alias mutt2="mutt -F ~/.mutt/muttrc_college"
------

To use your configuration, issue “mutt1” or “mutt2” at the prompt.

Managing your wireless connection with Wireless Tools for Linux

A lot of distributions offer their own wireless management tools.  While this can be helpful for a new user, an experienced GNU/Linux user knows that all these tools rely on the generic wireless extension offered by Wireless Tools for Linux.
Today I will show you how to manage your wireless connection by using a subset of the Wireless Tools (iwconfig, iwlist, and ifrename).

Note: I do not use wpa_supplicant.

Some required settings.

You need CONFIG_NET_RADIO=y in your kernel config (it creates /proc/net/wireless).  Also, your results from this tutorial will improve with Wireless Tools version 27 and above.  Use iwconfig –version to determine your version.

Make your interface consistent with ifrename.

ifrename allows you to assign a consistent name to each of your network interfaces.  Normally, interface names are dynamic, meaning that each interface is assigned a name on a first detected, first assigned basis.  Because each interface has some static elements, you can apply naming rules on them to provide a consistent name regardless of when the interface was detected.

Of course, you need to ascertain some information from each device before applying rules to them.  The file to edit is /etc/iftab.

Entries in /etc/iftab consist of a set of mappings: interface name and descriptors.  I find it easier to match devices based on their drivers.  Example entries can be found in `man iftab`.  I use:

b44 driver b44
iwl driver iwl3945

After you have finished editing /etc/iftab, add ifrename to your boot up scripts to automatically rename your devices.  You’ll need to make sure that the command is issued before the devices are brought up.  Use `ifrename -V -D` to see what would happen if you actually issued the command.

Managing the network.

iwconfig iwlist are your tools.

The first thing you usually do is search for available networks.  `iwlist scanning` will show all the available networks.

Once you find a network, connect to it with iwconfig.  iwconfig is your tool for configuring the wireless interface; it is normally used to connect to a network.  Usage is simple, usually in the form: iwconfig <interface> <option> <parameters>.  Typically you’ll be using the following:

iwconfig <interface> essid <ESSID>

iwconfig <interface> key <KEY>

That’s all there is too it.  You can view your current authentication settings with `iwlist auth`.