Search code examples
scriptingffmpegwavvideo-encodingbmp

Scriptable utility to convert BMPs + WAV to video (XviD)?


I'm looking for a scriptable utility to convert a bunch of BMPs and a WAV file into a video. XviD needs to be the output format. I'd like it to work on Linux (Ubuntu) if possible. A command line utility would be great, as I have 36 videos to create this way. A bash (or [insert favorite scripting language here]) script would be great for this. (I also need to play around with different video dimensions, but I can use other programs to resize.)

I've played around with VirtualDub (for Windows XP), but it doesn't seem to meet these needs. I could be wrong, though. Any pointers to examples would be great.

I'm also playing with ffmpeg. It seems to fit the bill perfectly, but I can't seem to get it to pull together the BMPs into a video. Here's what I'm trying:

for directory in $BMP_DIRECTORY_PATH/*
do
    ffmpeg \
        -f image2 \
        -i "$directory/Sequence %d%d%d%d%d%d.bmp" \
        -r 29.97 \
        -vcodec mpeg4 \
        -vtag xvid \
        \
        -i "$file/audio.wav" \
        -acodec libmp3lame \
        \
        $(basename $directory.avi)
done

And here's what it's saying back:

[...]

FFmpeg version 0.5-svn17737+3:0.svn20090303-1ubuntu6, Copyright (c) 2000-2009 Fabrice Bellard, et al.
  configuration: --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --extra-version=svn17737+3:0.svn20090303-1ubuntu6 --prefix=/usr --enable-avfilter --enable-avfilter-lavf --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --disable-stripping --disable-vhook --enable-libdc1394 --disable-armv5te --disable-armv6 --disable-armv6t2 --disable-armvfp --disable-neon --disable-altivec --disable-vis --enable-shared --disable-static
  libavutil     49.15. 0 / 49.15. 0
  libavcodec    52.20. 0 / 52.20. 0
  libavformat   52.31. 0 / 52.31. 0
  libavdevice   52. 1. 0 / 52. 1. 0
  libavfilter    0. 4. 0 /  0. 4. 0
  libswscale     0. 7. 1 /  0. 7. 1
  libpostproc   51. 2. 0 / 51. 2. 0
  built on Apr 10 2009 23:18:41, gcc: 4.3.3
[image2 @ 0x97e5ac0]Could not find codec parameters (Video: bmp)
/home/ben/Pending/1080p_export/6/Sequence %d%d%d%d%d%d.bmp: could not find codec parameters

I've seen a mailing list post about this, but what is suggested doesn't seem to work here.

UPDATE

Here's the updated script with multiple steps:

#!/usr/bin/env bash

# bmp+wav2xvid+mp3
# 
# Although it has a cryptic name, it's pretty descriptive.  This script consumes BMPs (Windows bitmaps) and WAVs (Microsoft AD-PCM Waveforms) to make an XviD (MPEG-4 video) movie.
# 
# By convention, you pass it a directory with one or more directories that contain:
#
#     * Frames named "frame_001.bmp", "frame_002.bmp", etc.
#     * Audio named "audio.wav"
# 
# Author: Benjamin Oakes

# FIXME: The audio doesn't get muxed correctly.  The A/V sync is off a little.  At the beginning it looks pretty okay, but by the end the mouths definitely don't match up with the words that are said.

#############################################################
# NOTE: SEE `ffmpeg -formats` for a list of available formats
#############################################################

# BMP_DIRECTORY_PATH="/home/ben/Outbox/ffmpeg.fixture/"
BMP_DIRECTORY_PATH="/media/Archival Data/Video Projects Backup/Video Projects/1080p_export_dual_gray/"

# Output settings
VTAG="xvid"
VCODEC="mpeg4"
ACODEC="libmp3lame"
DIMENSIONS="1000x562"
FPS="35"
CONTAINER="avi"

if [ -d "$BMP_DIRECTORY_PATH" ]; then
  echo "BMP directory exists"

  # for directory in "$BMP_DIRECTORY_PATH"/*
  # do
    directory="/media/Archival Data/Video Projects Backup/Video Projects/1080p_export_dual_gray/1"

    ffmpeg \
      -f image2 \
      -i "$directory/frame_%03d.bmp" \
      -vcodec mpeg1video \
      -sameq \
      \
      -r $FPS \
      "../tmp/$(basename "$directory.mpg")"

    ffmpeg \
      -i "../tmp/$(basename "$directory.mpg")" \
      -vcodec $VCODEC \
      -vtag $VTAG \
      -s $DIMENSIONS \
      -sameq \
      \
      -i "$directory/audio.wav" \
      -acodec $ACODEC \
      -ar 8000 \
      \
      -f $CONTAINER \
      -r $FPS \
      "../tmp/$(basename "$directory")-$VTAG-$VCODEC-$ACODEC-$DIMENSIONS-$FPS.$CONTAINER"
  # done
else
  echo "ERROR: BMP directory does not exist"
fi

UPDATE 2

Please see my answer for what I ended up getting to work.


Solution

  • This is what I ended up with, just for other people's reference.

    # bmp+wav2xvid+mp3
    # 
    # Although it has a cryptic name, it's pretty descriptive.  This script consumes BMPs and WAVs to make an XviD (MPEG-4 video) movie.
    # 
    # By convention, you pass it a directory with one or more directories that contain:
    #
    #     * Frames named "frame_001.bmp", "frame_002.bmp", etc.
    #     * Audio named "audio.wav"
    # 
    # Author: Benjamin Oakes
    
    # Output settings
    VTAG="xvid"
    VCODEC="mpeg4"
    ACODEC="libmp3lame"
    ABITRATE="128k"
    QSCALE="1"
    DIMENSIONS="1000x562"
    FPS="24000/1001"
    CONTAINER="avi"
    
    if [ -d "$BMP_DIRECTORY_PATH" ]; then
      echo "BMP directory exists"
    
      for directory in "$BMP_DIRECTORY_PATH"
      do
        ffmpeg \
          -f image2 \
          -r 24000/1001 \
          -i "$directory/frame_%03d.bmp" \
          \
          \
          -i "$directory/audio.wav" \
          \
          \
          -vcodec $VCODEC \
          -vtag $VTAG \
          -qscale $QSCALE \
          -s $DIMENSIONS \
          -r $FPS \
          \
          -acodec $ACODEC \
          -ab $ABITRATE \
          \
          "../tmp/$(basename "$directory").avi"
      done
    else
      echo "ERROR: BMP directory does not exist"
    fi