VCS Beyond Linux

Before the next release I'd like to make VCS work better in other OSes beyond Linux. Linux is my (current at least) OS
of choice and the one I'm not familiar with so it's also obviously the OS in which I develop and test VCS.
Thanks to virtualisation
gaining a lot of momentum I'm now able to try operating systems I've never worked with (and which I'm pretty sure
will make VCS choke in ways I never expected); e.g. the very last major feature, DVD vidcapping, is written in a way not compatible
with, at least, FreeBSD. I'll focus on making vcs work better (or at all) on ther systems for a while, let's see
how it turns out.

VCS 1.0.99 released

New version released, finally implementing DVD support (both ISO and DVD devices should work).
Also JPEG 2000 output, a more Polaroid™-like

polaroid mode 😉 (the older one has been renamed to photos); the timestamp is now reduced
for smaller captures plus the usual batch of fixes/tweaks.


Capturing from DVDs is a bit tricky, the filename is passed as an argument to -V while
the title number must be provided as if it were the file to capture, e.g.: $ vcs -V /dev/dvd 1

will capture the first title from the inserted DVD.

Passing 0 as DVD title will use the longest title in the disc (which is usually the main title):
$ vcs -V someiso.iso 0

DVD support *requires* lsdvd and fdisk (fdisk is used to detect the size of DVDs)
in this first version.

JPEG 2000

JPEG 2000 output (*.jp2 files) is used by passing the -j2 or --jpeg 2

New polaroid mode

As for bugfixes: I finally came across the previously unreproducible bug that made the polaroid
and overlap modes place all images on the same spot. Guess it was a problem with a newer version of
ImageMagick since I've also encountered a lot of problems with some of the commands I was using.
I've fixed all I was able to find.
As a side effect, I've reworked once again the alignment of the different sheets.

This will be renamed as 1.1.0 if it works well enough for others.

Script: man2ps, man2pdf, man2evince


  • $ man2ps command will generate a PostScript (.ps) file from command's manpage
  • Symlink or copy this script as "man2pdf" to create a PDF from a manpage.
  • Symlink or copy this script as "man2evince" to call evince on a temporary PDF of the manpage

# man2ps, (c) 2004,2005,2006,2009 Toni Corvera, published under a BSD license
# Saves a man page as either a PostScript (PS) or as a PDF file.
# This script is also used as a testbed for some experiments,
# as of now only rudimentary in-file localisation is kept, in the past
# the script could also be sourced and work as a function but it led to
# unwanted pollution of the environment.
# $Rev: 242 $
# Changelog:
# 0.11.0 (2009-03-09):
#     - Added man2evince
#     - Check for man page existence
# 0.10.0 (2006-06-27):
#     - First version with a changelog
#     - Explicit usage of bash
#     - Better use of bashisms
#     - Usage of /usr/include/sysexits.h -compatible exit codes
#     - Dropped support to be used as a function (sourced)
#     - Dropped support for long options
#     - Complete help message
#     - Wrapped localized strings into functions, may help parsing speed. Or maybe not.
#     - Added set -e
# 0.9.2 (2005)

set -e

# Current version
# Command name for information messages
CMD=`basename $0`

### Simple localisation support ###

# Language codes
declare -ir _EN=0 _ES=1 _CA=2
declare -a LANGS=( en es ca ) # Languages un the same order as their index
declare -i _L

# Error messages
error_nops2pdf() {
    local nopdf_strs=( "ps2pdf wasn't found, can't export to PDF"
                       "No se ha encontrado ps2pdf, no se puede exportar a PDF"
                       "No s'ha trobat ps2pdf, no es pot exportar a PDF" )
    echo ${nopdf_strs[$_L]} >&2

error_bad_cmdline() {
    local badcmdline_strs=( "Use -h to get usage instructions"
                            "Usa -h para obtener ayuda"
                            "Utilitza -h per obtenir ajuda" )
    echo ${badcmdline_strs[$_L]} >&2

error_notvalid_ver() {
    local allowedvers_strs=( "Only versions 2, 3 and 4 of ps2pdf are allowed"
                             "Sólo las versiones 2, 3 y 4 de ps2pdf están permitidas"
                             "Només les versions 2, 3 i 4 de ps2pdf estan permeses" )
    echo ${allowedvers_strs[$_L]} >&2

# Information messages
declare -r VERSION_STRING="${CMD} v${VER}, (c) 2004,2005,2006 Toni Corvera"

show_help() {
    # Localised functions
    en() {
        echo "$VERSION_STRING"
        echo "   saves a man page as a PostScript or PDF file"
        echo "Options:"
        echo "   -h         Show this help message"
        echo "   -p         Force PDF mode for output"
        echo "   -V VER     Use ps2pdf version 1.VER (VER must be one of 2, 3 or 4), "
        echo "              by default the newest available version is used"

    es() {
        echo "$VERSION_STRING"
        echo "   guarda una página de manual como archivo PostScript o PDF"
        echo "Opciones:"
        echo "   -h         Muestra este mensaje de ayuda"
        echo "   -p         Fuerza la salida a un archivo pdf"
        echo "   -V VER     Usa la versión 1.VER de ps2pdf (VER puede ser 2, 3 o 4), "
        echo "              por defecto se usa la versión más reciente disponible"

    ca() {
        echo "$VERSION_STRING"
        echo "   desa una pàgina de manual com arxiu PostScript o PDF"
        echo "Opcions:"
        echo "   -h         Mostra aquest missatge d'ajuda"
        echo "   -p         Força la sortida a un fitxer PDF"
        echo "   -V VER     Utilitza la versió 1.VER de ps2pdf (VER pot ser 2, 3 o 4), "
        echo "              per defecte s'utilitza la versió disponible més nova"


show_usage() {
    local usage_strs=(
                        "Usage: ${CMD} [options] <manual page>"
                        "Uso: ${CMD} [opciones] <página del manual>"
                        "Ús: ${CMD} [opcions] <pàgina del manual>"

    echo "${usage_strs[$_L]}"

# $1 => ps2pdf program name
show_ps2pdf_version() {
    local pdfver_strs=( "Using ps2pdf version:"
                        "Usando ps2pdf en su variante:"
                        "Fent servir ps2pdf en sa versió:" )
    echo "${pdfver_strs[$_L]} $1" >&2

# Language detection
# FIXME: is the precedence order correct?
    # Indirect variable reference, see
    eval val=$$i

    if [ "$val" ]; then
        case $val in
            es*) _L=$_ES ;;
            ca*) _L=$_CA ;;
            *)   _L=$_EN ;;
if [ -z $_L ]; then _L=$_EN; fi

### Core functionality ###

declare -i PDF=0 EVINCE=0

if [ $(basename "$0") == "man2pdf" ]; then
elif [ $(basename "$0") == "man2evince" ]; then

# Command line parsing
while getopts "hpV:" options ; do
    case $options in
        h) show_help && exit 0 ;;
        p) PDF=1 ;;
            if ! echo -n "$OPTARG" | egrep '^[234]$' >/dev/null 2>/dev/null ; then
                exit 64
            exit 64
shift $(($OPTIND - 1))

if [ -z "$1" ]; then
    exit 64

if [ $PDF -eq 0 ]; then
    man -t "$1" > "${1}.ps"
    # Use the newest ps2pdf
    if [ -z "$PS2PDF_VER" ]; then
        for prog in ps2pdf14 ps2pdf13 ps2pdf12 ps2pdf ; do
            ps2pdf=`which $prog` && break
        ps2pdf=`which ps2pdf1$PS2PDF_VER` || true

    if [ -z "$ps2pdf" ]; then
        exit 69

    show_ps2pdf_version $(basename "${ps2pdf}")
    if [ $EVINCE -eq 1 ]; then
        OUTPUT="$(tempfile --suffix=.pdf)"
    # Check if the command has a manpage...
    if ! whatis "$1" >/dev/null ; then
        man "$1" # Display man's error...
        exit $?
    man -t "$1" | ${ps2pdf} - > "$OUTPUT"
    if [ $? -eq 0 ] && [ $EVINCE -eq 1 ]; then
        evince "$OUTPUT"
        rm -f "$OUTPUT"
fi # PDF -eq 0

# vim:set ts=4 et ai: #

Downloadable file:

VCS update 2008-04-16: 1.0.12 released

New version released, it fixes highlights, which were broken in the last version and a couple of long-standing cosmetic bugs.

Also now requires minimum length before using the "end offset" i.e.: will only ignore a bit off the end of the video
if it's long enough, by default 19'30" (the default value was chosen based on the fact that most series are at least 20' long,
and since the automatic end offset is intended to skip credits, it's most useful with series and films). Your input is welcome
as always.

To change the minimum length set the desired value to variable MIN_LENGTH_FOR_END_OFFSET in your configuration file, e.g.:
echo MIN_LENGTH_FOR_END_OFFSET=\'1h30m\' >> ~/.vcs.conf # for 1h 30'

I just noticed a bug while editing this page :/ and it's been there for quite awhile… great… whatever, most probably few people, if anyone
suffered it, since it required a pretty specific timestamp format being used in the command-line.

Finally I've also re-added the black border after the highlights, which was removed a long time ago due to it breaking vcs back then.

See the changelog as usual for full details.

VCS update 2008-04-08: 1.0.11 released

New version released with a couple fixes and cosmetic touches.

Fixes include a workaround for cases in which mplayer outputted all-black (or all-equal) captures. Also slightly better
support for older/tighter systems (e.g. Damn Small Linux).

Most notably in the cosmetic side is better thumbnail alignment in extended mode (-e), slightly less padded captures and drop of milliseconds
when using mplayer (since they aren't meaningful at all).

See the changelog as usual for full details and credits.

I'm also providing a debian package now.

I was holding off a bit this release since there's still some known stuff to fix or refine but I'll rather publish now what I've
since, well, who knows when will be the next release 😉

Important note: this version's support for highlights (-l) is broken,
This version is deprecated for this reason, use the last version instead.
I'll update ASAP but if you need them
(does anyone use them anyway?) please use 1.0.10.

Script: video identification (Bash)

This script displays mplayer's information/identification lines of a multimedia file. Nowadays I prefer to use an undocumented feature of vcs (see below)


# This script displays mplayer's information/identification lines of a multimedia file
# Put in the public domain. <>

vididf() {
        mplayer -identify -frames 0 -ao null -vo null "$1" 2>/dev/null | grep ID_ | sort

for F in "$@"; do vididf "$F" ; done


$ vidid file.avi

VCS version:
$ vcs -Z idonly somefile.avi
=========== Mplayer Identification ===========
Length: 42:39.52
    Codec: XVID (Xvid (MPEG-4))
    Dimensions: 704x396
    FPS: 23.976
    Codec: 85 (MPEG Layer III (MP3))
    Channels: 2

=========== FFmpeg Identification ===========
Length: 42:39.51
    Codec: mpeg4 (MPEG-4)
    Dimensions: 704x396
    FPS: 23.98
    Aspect: 16/9
    Codec: mp3 (MPEG Layer III (MP3))
    Channels: 2

=========== Combined Identification ===========
Length: 42:38.01
    Codec: XVID (Xvid (MPEG-4))
    Dimensions: 704x396
    FPS: 23.976
    Aspect: 16/9 (1.7778)
    Codec: 85 (MPEG Layer III (MP3))
    Channels: 2

VCS update 2007-11-08: 1.0.10 released

New version released wth a bugfix and a couple new features: allow disabling timestamps and/or shadows.
See the changelog below.

I've also published a bit of information on the future of VCS and comments would be very welcome (in short, most probably, I'll be rewriting it in a different language than bash).

Finally, I'm moving the documentation into a wiki and filling in a bit more, will be live soonish I hope.

VCS OOP Rewrite?

Note: VCS stands for Video Contact Sheet *NIX, visit for details.

I'm considering an alternative language in which to rewrite VCS. It must support OOP well enough and be relatively common-place. Current candidates are Java, Python and PHP5. Comments/suggestions/preferences are welcome, either here or by mail ( (but leave alone language hatred/fandom!).

VCS is, no matter how you look at it, a script. It's a piece of software that basically interfaces with other
pieces of software simplifying a task that could be done manually (yet in a harder way) with them. So a scripting language was the right choice, bash is the one I know better, it is really
powerful and most computers already have it installed. The-right-choice… *but*. Writing a relatively long and complex piece
of code and keeping it as modular as possible in bash is a pain; anyone that may have looked at the code should agree it's hard to read, let alone maintain. So, almost from the start I've been considering alternatives to bash.

The problem is I want to maintain the feats that make a script desirable (after all, it will remain technically a script as I have no intention to interface directly with ImageMagick's or libavcodec's libs). These
features can be summarised as cross platform, no compilation and a single file approach: users should be able to download the script file and run it right away (after filling dependencies of course, just as currently).

My language candidates are PHP version 5, Python and Java.

Java, while the less script-ish of them can still be single-file (JAR) and would need no compilation (by final users). PHP since version 5 has a lot more power in regards of OOP and of course it has that massive
library web developers love and hate 🙂 Python is the least known by me, it's meaningful whitespace still feels weird but apparently it's a very good option for OOP software.

I'm currently rewriting vcs in PHP and I'm even more convinced to switch languages after having some more power on my hands. I fear though that switching away from a shell script might make some people overlook vcs.

Comments would be greatly appreaciated.

Scroll to Top