Package: ffmpeg2theora
Version: 0.16-2+b1
Output from a video-processing script of mine:
[1]+ sf -t FakePipe:debug=0 -t Scratch ffmpeg2theora -c 0 -o t.ogg -f
image2 /volatile/ian/tmp/d/composed/frame%06d.ppm --inputfps 30
[2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31][32][33][34][35][36][37][38][39][40][41][42][43][44][45][46][47][48][49][50][51][52][53][54][55][56][57][58][59][60][61][62][63][64][65][66][67][68][69][70][71][72][73][74][75][76]Input
#0, image2, from '/volatile/ian/tmp/d/composed/frame%06d.ppm':
Duration: 00:00:16.0, start: 0.000000, bitrate: N/A
Stream #0.0: Video: ppm, rgb24, 640x970, 25.00 fps(r)
Resize: 640x970
0:00:00.50 audio: 0kbps video: 9420kbps
The `[<number>]' are progress indication and can be disregarded.
Note that I invoke
ffmpeg2theora -c 0 -o t.ogg -f image2 \
/volatile/ian/tmp/d/composed/frame%06d.ppm --inputfps 30
but ffmpeg2theora reports
Stream #0.0: Video: ppm, rgb24, 640x970, 25.00 fps(r)
`sf' is subterfugue; I'm running ffmpeg2theora under subterfuge to
solve the following problem:
With the image2 `format' I have to supply all of the files (ppms in
this case) for the whole video, as existing disk files, before
starting. This requires an enormous amount of disk space, and is very
slow (because all of the ppms have to be written out to disk and then
read back in).
With the image2pipe `format', which ought to be the answer to this
problem, I find that ffmpeg2theora, like ffmpeg, cannot cope when it
gets a short read(2). It prints messages about buffer underruns.
So instead I have written an sf trick. Subterfugue is an strace-based
trickery framework which allows supervisory modules called `tricks' to
intervene in a program's activities including system calls. The
`FakePipe' module allows me to supply the `image2' format with a
directory full of named pipes; it tricks ffmpeg into seeing these as
normal disk files, while allowing the data provider to open and write
to each file one at a time.
I have attached the script for your information. If necessary I can
supply suitable input data and a copy of the sf trick and other
relevant files but you probably don't want to dive that deeply into my
situation.
Ian.
#!/bin/bash
set -e
fail () { echo >&2 "bikecams-unify: error: $1"; exit 127; }
basis=0
offset=true
max=''
while [ $# != 0 ]; do
val="${1#*=}"
case "$1" in
--tmpdir=*) tmpdir="$val" ;;
--frames=*) max="$val" ;;
--start-frame=*) basis="$val" ;;
--no-offset) offset=false ;;
--) shift; break ;;
-*) fail "unknown option \`$1'" ;;
*) break ;;
esac
shift
done
test $# = 3 || \
fail 'usage: .../bikecams-unify [--tmpdir=T] FRONT.avi REAR.avi OUTPUT.thing'
front="$1"
rear="$2"
output="$3"
if [ "x$tmpdir" = x ]; then
trap 'set +e; wait; rm -rf -- "$tmpdir"; exit 127' 0
tmpdir="`mktemp -dt`"
rm_tmpdir=true
else
rm -rf -- "$tmpdir"
mkdir -- "$tmpdir"
rm_tmpdir=false
fi
frame=frame%06d.jpg
oframe=frame%06d.ppm
if [ "$max" ]; then
t_max="-t $(( ($max + 29) / 30 ))"
fi
x () { echo >&2 "+ $*"; "$@"; }
dmjpeg () {
mkdir -p "$tmpdir/$2"
x ffmpeg $t_max \
-i "$1" -f image2 "$tmpdir/$2/$frame" \
-f s8 "$tmpdir/$2.sb"
}
dmjpeg "$front" front
dmjpeg "$rear" rear
if $offset; then
${0/unify/audio} --not-interactive \
<"$tmpdir"/front.sb \
3<"$tmpdir"/rear.sb \
>"$tmpdir"/offset
read <"$tmpdir"/offset offset_ausamples offset_seconds offset_frames
else
offset_ausamples=0
offset_seconds=0
offset_frames=0
fi
# weird noise thing:
# sox -c1 -r8000 d/tmp/rear.sb d/tmp/t.wav noiseprof prof
# sox -v0.5 -c1 -r8000 d/tmp/rear.sb d/tmp/t.wav noisered prof 0.1
initoffsets () {
if [ $offset_ausamples -lt 0 ]; then
atrimfront=$(( -$offset_ausamples ))
atrimrear=0
ifront=$(( $basis-$offset_frames ))
irear=$basis
else
atrimfront=0
atrimrear=$(( $offset_ausamples ))
ifront=$basis
irear=$(( $basis+$offset_frames ))
fi
icomposed=0
}
perframeloop () {
ifile front
ifile rear
icomposed=$(( $icomposed + 1 ))
if [ "$max" -a "$icomposed" -gt "$max" ]; then break; fi
f=`printf "%s/composed/$oframe" "$tmpdir" "$icomposed"`
}
ifile () { eval '
i'$1'=$(( $i'$1' + 1))
f=`printf "%s/$frame" "$tmpdir"/'$1' $i'$1'`
if ! test -f "$f"; then break; fi
f'$1'="$f"
'
}
pbmmake -black 1 10 >"$tmpdir"/border
mkpipe () {
rm -f -- "$1"
mkfifo -m600 -- "$1"
}
#mkpipe "$tmpdir"/sentinel
#exec 3<>"$tmpdir"/sentinel
#exec 4<"$tmpdir"/sentinel
rm -rf "$tmpdir"/composed
mkdir "$tmpdir"/composed
initoffsets
trimaudio () { x sox -c1 -r8000 "$tmpdir/$1".sb "$tmpdir/$1".wav trim ${2}s; }
trimaudio front $atrimfront
trimaudio rear $atrimrear
x sox -M "$tmpdir"/rear.wav "$tmpdir"/front.wav -c2 "$tmpdir"/output.wav
while true; do
perframeloop
mkpipe "$f"
printf "(%d)\r" $icomposed
done
echo
if false; then
PYTHONPATH="`dirname $0`" \
x sf -t FakePipe:debug=0 -t Scratch \
ffmpeg -y -r 30 \
-f image2 -vcodec ppm -i "$tmpdir"/composed/$oframe \
-i "$tmpdir/output.wav" \
-acodec copy \
-vcodec mpeg4 -f avi "$output" \
&
## -f mpeg -acodec copy -vcodec mpeg4 \
## "$output" \
## &
else
PYTHONPATH="`dirname $0`" \
x sf -t FakePipe:debug=0 -t Scratch \
ffmpeg2theora \
-c 0 -o "$output" \
-f image2 "$tmpdir"/composed/$oframe --inputfps 30 \
&
## -f image2pipe --inputfps 30 "pipe:.ppm" &
##
##x strace -vvtt -ot
# -f wav output.wav \
# --audiostream 1 \
fi
reencode_pid=$!
initoffsets
while true; do
perframeloop
printf "[%d]" $icomposed
pfront="$ffront.ppm"
prear="$frear.ppm"
djpeg -pnm "$ffront" >"$pfront"
djpeg -pnm "$frear" >"$prear"
pnmcat -tb -black "$pfront" "$tmpdir"/border "$prear" >"$f"
rm -- "$pfront" "$prear"
done
exec 4<&-
sleep 1
x wait $reencode_pid
if $rm_tmpdir; then
trap '' 0
rm -rf -- "$tmpdir"
fi