Your web-browser does not support CSS, or you have CSS switched off. For a better web experience, I recommend using a modern browser. Until then, an older version of this site will look better in your browser.

Sat, 23 Jun 2007

How to waste an evening

One of a series on my continuing adventures in computer drama.

I thought I’d take a few minutes to upload this video of the Harvard Law School building-moving project to YouTube. As usual, the project stretched into three or four hours, complete with the usual triumvirate of poorly-documented software, inexplicable error messages, and mysterious crashes.

First, the fun part:

There are also photos.

Now, the geeky part. If you’re not a computer nerd, the rest of this post may bore you.

I wanted to concatenate a bunch of videos I took with my camera, rotate the ones that I took at a 90 degree angle, strip out a few seconds of chaff, and append a title card to each end. And I wanted to speed them up. It’s impressive to see a house creep down a street at all, but on the Internet, no-one wants to spend more than a minute on it.

I settled for concatenating the videos. (And speeding them up.) Here’s what actually worked, after several zillion different things that didn’t:

  • Use transcode on Linux to concatenate the AVI files together. (Concatenating them with cat and running them through mencoder is a bad idea (despite what some may suggest ) – it produced a file that crashed most of other programs I tried to run on it. Concatenation is easy: avimerge -o out.avi -i in1.avi in2.avi in3.avi …
  • Use VirtualDub” to speed up the video. Go to Video->Frame Rate. Click “Change to ___ frames per second” and set that to some multiple of the original frame rate (I used 10, so 15 fps became 150 fps). To ensure that the file is not insanely large, you also have to decimate the video. Click “Decimate by ___” and fill in the multiple of the frame rate you used (10, in this case.) N.B.: transcode is a Linux program and VirtualDub is a windows program, so I needed two boxen just to upload a video to YouTube! Of course, I’m hardly the first to rant about this stuff.
  • Compress the video (Video->Compression), because YouTube only handles videos up to 100MB. I just picked the first codec that worked “Indeo® video 5.10”). (I also dropped the audio (Audio->no output, for a small savings.)
  • Upload it. This was the easy part.

Now, for the stuff that didn’t work:

  • VirtualDub has a wonderful interface for a piece of free video software. It may be the only piece of free video software with a wonderful interface. The problem with VirtualDub is that it’s fantastically finicky about the video it will take. This became an issue when I tried to paste my title cards (15 fps) onto my video (15.00015 fps). Yes, of course, it refused.
  • Avidemux, despite being possessed of a…utilitatian (but very functional) GTK2 interface, didn’t refuse to concatenate video because of a tiny difference in the frame rate. The problem was that it would randomly stop opening the videos it produced for reasons I never understood. I’d use it to append a bunch of mpegs together. (These were either straight from the camera or from the camera via VirtualDub, where I’d rotated and cropped them.) It would happily save the concatenated video to a file…then refuse to open it. I’d open one of those files, and the application would instantly quit without so much as an error message.
  • So I switched back to Linux. I took the clips that I’d rotated and cropped and tried assembling them using the catandmencoder method. Flop: I couldn’t slice out the extra frames using the VirtualDub decimator. VirtualDub would abort 1/3 of the way in and complain that the file was corrupt. Same deal if I used the avimerge technique.
  • So I switched to Linux again. My guess as to how to drop the unnecessary frames didn’t work: I tried the –frame_interval option to transcode…but transcode promptly crashed. Like this:
jdb@bigbox:/mnt/max/park$ transcode -i merge.avi --frame_interval 120 -o fast.avi
transcode v1.0.3 (C) 2001-2003 Thomas Oestreich, 2003-2004 T. Bitterberg
(dvd_reader.c) no support for DVD reading configured - exit.
[transcode] (probe) suggested AV correction -D 0 (0 ms) | AV 0 ms | 0 ms
[transcode] auto-probing source merge.avi (ok)
[transcode] V: import format    | MJPG RIFF data, AVI (V=ffmpeg|A=avi)
[transcode] V: import frame     | 320x240  1.33:1
[transcode] V: bits/pixel       | 1.562
[transcode] V: decoding fps,frc | 15.000,0
[transcode] V: Y'CbCr           | YV12/I420
[transcode] A: import format    | 0x1     PCM          [11024, 8,1]  176 kbps
[transcode] A: export           | disabled
[transcode] V: encoding fps,frc | 15.000,13
[transcode] A: bytes per frame  | 733 (734.933333)
[transcode] A: adjustment       | 1936@1000
[transcode] V: IA32/AMD64 accel | sse (sse 3dnowext 3dnow mmxext mmx asm C)
tc_memcpy: using sse for memcpy
[transcode] warning : no option -y found, option -o ignored, writing to "/dev/null"
[transcode] V: video buffer     | 10 @ 320x240
[import_avi.so] v0.4.2 (2002-05-24) (video) * | (audio) *
[import_ffmpeg.so] v0.1.12 (2004-05-07) (video) ffmpeg: MS MPEG4v1-3/MPEG4/MJPEG
[export_null.so] v0.1.2 (2001-08-17) (video) null | (audio) null
[import_avi.so] format=0x1, rate=11024 Hz, bits=8, channels=1, bitrate=176
[transcode] input is mjpeg, reducing range from YUVJ420P to YUV420P
[filter.c] Filter "levels=output=16-240:pre=1" with args (levels=output=16-240:pre=1)
[filter.c] Filter "levels=output=16-240:pre=1" not loaded. Loading ...
[filter.c] Loading (levels=output=16-240:pre=1) ..
[filter_levels.so]: v1.0.0 (2004-06-09) Luminosity level scaler #0
[filter_levels.so]: scaling 0-255 gamma 1.000000 to 16-240
[filter_levels.so]: pre-processing filter
[mjpeg @ 0xb6953c68]invalid id 23618.38 fps, EMT: 0:05:53, ( 0| 0| 0)
Segmentation fault (core dumped)

(Sharp-eyed readers will note that that command wouldn’t have done anything anyway, because the computer complained that I didn’t pass a -y argument, so it wrote its output to /dev/null. I didn’t notice this until just now. I tested it with an actual -y argument: -y mjpeg,null (because the input was mjpeg). That also bombed:

jdb@bigbox:/mnt/max/park$ transcode -i merge.avi --frame_interval 120 -o fast.avi -y mjpeg,null
transcode v1.0.3 (C) 2001-2003 Thomas Oestreich, 2003-2004 T. Bitterberg
(dvd_reader.c) no support for DVD reading configured - exit.
[transcode] (probe) suggested AV correction -D 0 (0 ms) | AV 0 ms | 0 ms
[transcode] auto-probing source merge.avi (ok)
[transcode] V: import format    | MJPG RIFF data, AVI (V=ffmpeg|A=avi)
[transcode] V: import frame     | 320x240  1.33:1
[transcode] V: bits/pixel       | 1.562
[transcode] V: decoding fps,frc | 15.000,0
[transcode] V: Y'CbCr           | YV12/I420
[transcode] A: import format    | 0x1     PCM          [11024, 8,1]  176 kbps
[transcode] A: export           | disabled
[transcode] V: encoding fps,frc | 15.000,13
[transcode] A: bytes per frame  | 733 (734.933333)
[transcode] A: adjustment       | 1936@1000
[transcode] V: IA32/AMD64 accel | sse (sse 3dnowext 3dnow mmxext mmx asm C)
tc_memcpy: using sse for memcpy
[transcode] V: video buffer     | 10 @ 320x240
[import_avi.so] v0.4.2 (2002-05-24) (video) * | (audio) *
[import_ffmpeg.so] v0.1.12 (2004-05-07) (video) ffmpeg: MS MPEG4v1-3/MPEG4/MJPEG
[export_null.so] v0.1.2 (2001-08-17) (video) null | (audio) null
[export_mjpeg.so] v0.0.5 (2003-07-24) (video) Motion JPEG | (audio) MPEG/AC3/PCM
[import_avi.so] format=0x1, rate=11024 Hz, bits=8, channels=1, bitrate=176
[transcode] input is mjpeg, reducing range from YUVJ420P to YUV420P
[filter.c] Filter "levels=output=16-240:pre=1" with args (levels=output=16-240:pre=1)
[filter.c] Filter "levels=output=16-240:pre=1" not loaded. Loading ...
[filter.c] Loading (levels=output=16-240:pre=1) ..
[filter_levels.so]: v1.0.0 (2004-06-09) Luminosity level scaler #0
[filter_levels.so]: scaling 0-255 gamma 1.000000 to 16-240
[filter_levels.so]: pre-processing filter
*** glibc detected *** transcode: malloc(): memory corruption: 0x080f97a8 ***
======= Backtrace: =========
/lib/libc.so.6[0xb7e8682d]
/lib/libc.so.6[0xb7e8726c]
/lib/libc.so.6(__libc_memalign+0xab)[0xb7e8812b]
/usr/lib/libavutil.so.1d(av_malloc+0x2d)[0xb7fc155d]
======= Memory map: ========
<snip>
Aborted (core dumped)
  • I couldn’t find an equivalent option in mencoder, so I decided that the rotate-and-crop videos must have been corrupted. I ditched them and went back to the the raw ones from the camera. After some fiddling, these actually worked.
  • In retrospect, I probably could have tried using VirtualDub to assemble the cropped-and-rotated videos (I didn’t before, because I was trying to add my title cards, which it wouldn’t do – at least, I couldn’t produce title cards that it would take.) Ah, well. Next time.