Reply
Thread Tools
Posts: 21 | Thanked: 18 times | Joined on Aug 2011
#1
I realise this may not be of use to many people these days, but I wanted to use the webcam of the N810 to record videos of me talking, to send to my children while I'm away. Couldn't find a way to do it, not without audio syncing problems or poor quality video.

So I spent far too long messing around and found a solution that works for me. I can record a minute or two (probably longer) of properly sync'ed video/audio in valid MPEG4 and email it to my kids. I'm posting this in case it's of any use.

Note that this script has been tweaked many times and contains a lot of comments about my progress. It's useful for me, and works for me, but may not work for you. As usual, no warranties, etc.

You need Easy Debian, and ffmpeg installed within it (I had to do apt-get update first, then apt-get ffmpeg). You also need mplayer in Diablo (for trimming; you can remove this from the script if you like).

Anyway, here it is. Save it as a script in MyDocs or elsewhere on the internal memory (not internal memory card), chmod +x and run it.

Test reports, improvements and enhancements welcome.

PS. If you don't already have alsa working in Easy Debian, you will probably need to do that. Search my other posts for details.

Code:
#!/bin/sh

# Usable Nokia N810 camera audio/video capture - AlexC 2012

# uses either Gstreamer (Maemo) & ffmpeg (Easy Debian) or ffmpeg & arecord (ED). The latter is better.
# also uses mplayer (Maemo) for trimming, but you could do away with that and have slightly untidier file starts/ends. 

# This works best for speech in good lighting without moving too much. If you start shifting around a lot, the a/v sync might drift (with Gstreamer, that is; it seems better with ffmpeg/arecord) and offset might change (I think the camera takes longer to wake up in low light).

# note liberal use of '2>&1 |grep whatever' and '2>/dev/null' etc., to limit verbosity. If you want (much) more feedback on what's happening, remove these redirections.

# set this to 1 if you want to use the Gstreamer method, but sync issues will be worse and probably so will video quality (double encoding)
GSTVERSION="0"

# If you still get offset/sync issues, rebooting might help, or change offset in the conversion commands.

# No checks are done for existence of output medium, so make sure it exists and has sufficient free space!

# This seems to be the best way to record video with audio from N810 camera. The 'Videocamera' app from 2008 can be force-installed, but although the sync is better within the app itself, the quality is much worse and the video format is corrupt/out of sync in everything else.

# ffmpeg capture within Easy Debian works for video, but not audio: I tried with -f alsa -i default and hw:0,0 etc., but it fails to access the audio device (there's nothing suitable in /dev that I can find). For reference, here's as far as I got:

# ffmpeg -y -f alsa -ac 1 -i default -f video4linux2 -i /dev/video0 -s 176:144 -vtag DIVX -vcodec mpeg4 -acodec pcm_s16le /media/mmc1/ffmpeg.avi

# The same problem occurs with the Maemo version of ffmpeg, but even worse because that's older than the ED version. Don't bother with it.

# So instead I set up a parallel audio recording in ED via arecord, then use ffmpeg to put the two together.

# The alternative gstreamer method in this script does work, but has a/v sync errors (a known issue that might relate to the camera driver). You can't compress on the fly, but using ffmpeg afterwards is useful anyway to boost volume, adjust a/v lag, etc.

# Gstreamer version by qole originally from here: http://talk.maemo.org/showthread.php?p=171769
# gst-launch-0.10 gconfv4l2src ! 'video/x-raw-yuv,width=320,height=240,framerate=(fraction)15/1' ! hantro4200enc profile-and-level=5 bit-rate=515 ! queue ! mux.  dsppcmsrc ! 'audio/x-raw-int,rate=8000,channels=1' ! queue ! mux. avimux name=mux ! filesink location=/media/mmc1/raw.avi
# For Gstreamer you'll need to go into red pill mode in Maemo and install, at least, the gstreamer0.10-tools package. If you don't have gstreamer0.10-plugins-good and gstreamer0.10-hantro installed, do that too. But you probably already have that, as I think OS2007 and OS2008 include them by default.

# putting CPU into performance mode may help (or may reduce available DSP grunt, so perhaps don't)
sudo /sbin/cpu-perform

if [[ "$GSTVERSION" == "1" ]]
then

	read -p "Press Enter to begin video capture..." blah

	# Play with frame rate here; was 15/1. Any way to force fixed frame rate to help sync? Could try 320x240 instead of 176x144 (and in the ffmpeg command), but get everything else right first. What's the camera's default resolution? Supposedly 640x480. Hmm.

	# Launch as a separate process so we can neatly close it
	gst-launch-0.10 v4l2src ! 'video/x-raw-yuv,width=176,height=144,framerate=(fraction)15/1' ! hantro4200enc profile-and-level=1007 bit-rate=515 ! queue ! mux. dsppcmsrc ! 'audio/x-raw-int,rate=8000,channels=1' ! queue ! mux. avimux name=mux ! filesink location=/media/mmc1/gst_raw.avi &

	echo -e "\n"

	read -p "RECORDING! Press Enter to end video capture..." blah

	# this is equivalent to ctrl-c, the only neat way to close a live gstreamer feed
	killall -2 gst-launch-0.10

else

	echo -e "\nPreparing...\n"
	# run ffmpeg and arecord first with no switches, so they're cached, otherwise the lag is much greater the first time the ED image is mounted (e.g. after reboot) because they take a while to load. Do this separate to the main 'debbie' because otherwise audio sometimes fails to record.
	debbie "ffmpeg --help" 1>/dev/null 2>/dev/null
	debbie "arecord --help" 1>/dev/null 2>/dev/null

	# run arecord and ffmpeg simultaneously, kill arecord when ffmpeg quits
	# first wait a few seconds for Debian to settle, to improve chances of both processes launching simultaneously
	# define video codec here so we don't encode twice
	debbie "sleep 2; echo -e '\nPress Enter to begin video capture...'; read blah; echo -e '\nRECORDING! Press \"q\" to end video capture...\n'; arecord /media/mmc1/temp_audio.wav -f S16_LE & ffmpeg -y -f video4linux2 -s 176:144 -i /dev/video0 -vtag DIVX -vcodec mpeg4 -b 200k /media/mmc1/temp_video.avi; killall arecord" 2>/dev/null |grep Press

fi

# Now compress/convert it. This needs ffmpeg in Easy Debian (it's newer than Maemo version).

echo -e "\nNow converting. this may take a while...\n"

# use epoch seconds as filename stem
NEWFILENAME=`date +%s`".avi"

if [[ "$GSTVERSION" == "1" ]]
then

	# Gstreamer video has sync issues that need to be handled.
	# Play with vol and also a/v offset seconds (for offset you need to include input file twice, once for audio & once for video, and the map switches), which might hide sync issues a bit. Actually, the setpts value is what really matters; changing the speed of one stream to match the other (because the camera output rate is wrong), otherwise they drift apart regardless of offset. -async is supposed to fix this on its own, but won't. I suspect the source video isn't properly time-stamped, if at all. Play with -b (bit-rate) setting to trade off quality against file size.

	debbie ffmpeg -i /media/mmc1/gst_raw.avi -itsoffset 0.6 -i /media/mmc1/gst_raw.avi -map 1:0 -map 0:1 -vol 2048 -s 176:144 -r 15 -vf "setpts=1.04*PTS" -vtag DIVX -vcodec mpeg4 -b 200k -acodec libmp3lame -ac 1 -ar 8000 -ab 64k /media/mmc1/$NEWFILENAME

else

	# first some cleverness to identify the video length in seconds, so we can chop off any spurious audio later, because arecord runs on a bit after ffmpeg ends. Can also remove the no-video offset at the start
	VIDLENGTH=`mplayer -identify -ao null -vo null -frames 0 /media/mmc1/temp_video.avi 2>&1 |grep ^ID_LENGTH= | cut -d = -f 2`

	# how much the audio is offset vs the video (my estimate)
	OFFSET=0.7

	# sync seems better with ffmpeg/arecord, but still need offset
	# must compress audio, but just copy video stream to avoid re-encoding
	debbie "ffmpeg -ss $OFFSET -i /media/mmc1/temp_audio.wav -i /media/mmc1/temp_video.avi -acodec libmp3lame -ac 1 -ar 8000 -ab 64k -vol 2048 -vcodec copy -t $VIDLENGTH -async 3 /media/mmc1/$NEWFILENAME 2>&1|grep 'video:'" 2>/dev/null

fi

# Now clean up

if [[ -e /media/mmc1/temp_video.avi ]]
then
    rm /media/mmc1/temp_video.avi
fi
if [[ -e /media/mmc1/temp_audio.wav ]]
then
    rm /media/mmc1/temp_audio.wav
fi
if [[ -e /media/mmc1/gst_raw.avi ]]
then
    rm /media/mmc1/gst_raw.avi
fi

# revert CPU back to on-demand (may be disabled; see earlier)
sudo /sbin/cpu-ondemand

echo -e "\nFinished! Video is stored on removable memory card (/media/mmc1/) as $NEWFILENAME\n"

read -p "Press Enter to watch it." blah

# Play it: could do this with mplayer, but this is fine for low-resolutions
dbus-send --session --print-reply --type=method_call --dest=com.nokia.mediaplayer /com/nokia/mediaplayer com.nokia.mediaplayer.mime_open string:"file:///media/mmc1/$NEWFILENAME"

Last edited by alexc; 2012-05-16 at 07:11. Reason: added note about Alsa; slight improvements to trim code
 

The Following 7 Users Say Thank You to alexc For This Useful Post:
Reply

Thread Tools

 
Forum Jump


All times are GMT. The time now is 01:51.