Recording sound / audio from Webcam Microphone.
Introduction
This might be simple to some people, and better ways probably exists, but to get started for beginners like myself, this method is working for me.
It records audio in a seperate file each time an event happens. It records from the microphone on the webcam that detects the motion. Motion on multiple cameras also work.
Detailed Description
Warning: It is important not to add more webcams than the CPU can handle. If the computer gets too busy, then strange errors might occur. So keep the frame rate low!
To get the audio correct in time it is important to have a long video post capture (e.g. 25) and a small gap (e.g. 1).
This example will give video files with an overhead of 5 seconds extra video in the end even though no motion is detected for the last 5 seconds. This is done to avoid too many small videofiles when something e.g. moves and stops for 1 second and then moves again.
Attached Files
Installation
The program "arecord" needs to be installed on your system and you need a full working "motion" installation on your system.
Change the path /home/mh/motion_data/ to the path where you want the audio files to be storred.
Edit your motion.conf file to have these specified values (example, that works for me):
on_event_start arecord -f S16_LE -r 22050 -D plughw:%t /home/mh/motion_data/%Y%m%d_%H%M%S_%t.wav
on_event_end ps -ef | grep arecord | grep plughw:%t | grep -v grep | awk '{print $2}' | xargs kill -9
post_capture 25
gap 1
You might want to try with these settings in your motion.conf (if you only have one camera) or in your thread-files (if you have many cameras). They works for me:
width 320
height 240
framerate 5
minimum_motion_frames 1
pre_capture 0
post_capture 0
minimum_gap 0
max_mpeg_time 0
low_cpu 2
output_all off
ffmpeg_cap_new on
ffmpeg_cap_motion off
ffmpeg_timelapse 0
ffmpeg_bps 400000
ffmpeg_variable_bitrate 2
ffmpeg_video_codec mpeg4
ffmpeg_deinterlace off
Users Guide
Playing back the video and audio can be done with mplayer.
Or it can be re-encoded to one file including both audio and video with mencoder.
Future requests
The audio should be stored in a compressed format that does not use too much CPU while storing it (realtime).
The audio and video should be merged to one file automatically.
The end of the video file where no motion is detected (due to post_capture 25) should be deleted automatically after the event ends. The only reason for having it is to avoid splitting it up to more files if there is a pause with no motion through (up to) 24 frames and then the motion continues.
The
kill -9 used in the on_event_end is not a nice way to kill it, but normal
kill did not work for some reason.
Possible way to record compressed audio
I have done some research and found, I suppose, not bad possible solution. This is not "ready_to_go" but more likely "where_to_find".
First of all of course we have ffmpeg since Motion need it and ffmpeg can record from /dev/dsp. My system is MOPSLinus that is russian Slackware 11 and it turned out, that I already have installed very powerfull sound utility "sox" (Sound eXchange - universal sound sample translator,
http://sox.sourceforge.net/). Sox itself can grab audio from /dev/dsp and record compressed, but its main power that it can convert audio from one format to another with changing samples rate, channels (mono-stereo), sample size (word, byte, etc), and sample encoding (signed linear, unsigned linear, u-law, etc). Sox can even applies some effects, one of which is noise reduction and it really and not bad works in real time (see "man sox"). Two short commands "play" and "rec" are sox wrappers.
So right away three variants for recording compressed sound appears:
1) ffmpeg grabs compress and writes
2) sox grabs and writes stdout with tuned parameters | compression utility (lame, oggenc, speexenc, tcat(libgsm), faac, flac) reads stdin and writes file
3) sox itself
And our task became not "how to" but "what to peek". I looked over several variants and fixed on this
...
on_event_start /usr/local/bin/ffmpeg -f audio_device -i /dev/dsp -vn -ar 32000 -ab 32 -ac 1 -acodec aac /root/motion/v/a/%Y-%m-%d-%H-%M-%S.aac
on_event_end killall -2 ffmpeg
...
This works for me but not long time and so this is not well tested. If you will test this and other variants, please post your results here. I'll put most of my tests scripts in attachment (sorry for mishmash :)
PS
1. Possible you will need first to turn on microphone with some mixer utility in order to record ever anything. Use KMix in KDE, "alsamixer" in interactive runlevel 3, and "amixer" in automated unwatched mode (for me "amixer sset Mic 29% cap" in rc.local works)
2. I have ffmpeg-checkout-2007-01-28 and I exactly remember that in ffmpeg versions recently before mine, command line arguments for grabbing audio were different.
Uff, thats all for the time present.
--
DmitryBolshakoff - 17 Mar 2007
A much nicer way to end the recording would be send a sigterm to the process using pkill and a search string, which is basically a regular expression.
Using the example above I would pick out something that guarantees uniqueness
on_event_end pkill -SIGTERM -f "^arecord -f S16_LE -r 22050 -D plughw:%t /home/mh/motion_data/"
I'm doing something a little different, piping arecord through lame and multiple cameras eg
on_event_start arecord -f cd -r 44100 -c 2 -t raw | lame -x -h -b 256 - /data/cam1/%t_%Y-%m-%d_
M-%S.mp3
on_event_end pkill -SIGTERM -f "^lame -x -h -b 256 - /data/cam1/"
Works and if you have your search string nice and tight you won't have any risk of data corruption, closing the wrong thread or not closing a thread at all.
--
LeonWright - 26 Sep 2008
The version of arecord in ALSA 1.0.23 (included in Ubuntu 10.10) has an option to write the process ID to a file: --process-id-file. This can make the kill event simpler. There are also options to start a new file after an interval, start a new file on receipt of a signal, and create a date-based directory structure, using the same techniques as Motion. See man arecord for details.
--
JohnSauter - 13 Oct 2010
What would be good if the sound was built in to the video. Not another file.
--
RaymondDay - 30 Jan 2016
Why Motion can't decode frames for motion detection, and once detected, use ffmpeg to write mixed video and audio to file from a source cam without transcoding, while also saving some pictures. Once detection shows the motion is stopped, Motion would stop ffmpeg writing the stream to file. This method needs very low CPU for writes, and will produce high quality videos of each detected event with embedded audio plus a series of jpeg pictures for each event for email notifications.
--
ZamarAcido - 18 Apr 2016
Building upon all the comments and solutions, I created a couple scripts and it works perfectly.
## motion.conf
movie_filename %m-%d-%Y_%H:%M:%S
on_event_start /bin/bash /usr/bin/audiorecord.sh %m-%d-%Y_%H:%M:%S
on_event_end /bin/bash /usr/bin/audiokill.sh
# /usr/bin/audiorecord - starts a audio recording with same filename.wav as movie.avi and creates a same filename.pid with the PID of the arecord process.
#!/bin/bash
AUDIO=$1
DIR=/dir/to/motion/videos
if pgrep -f "arecord"; then sudo pkill -9 -f "arecord -f cd -r 22050 -D plughw:2,0"; fi
arecord -f cd -r 22050 -D plughw:2,0 ${DIR}/${AUDIO}.wav &
PID=${BASHPID}
echo "${PID}" > "${DIR}/${AUDIO}.pid"
# audiokill.sh
#!/bin/bash
DIR=/dir/to/motion/videos
PIDS=$(find ${DIR} -type f -iname "*.pid" -printf "%f\n" | cut -d. -f1)
while read -r x; do
pgrep -F "${x}.pid" && sudo pkill -9 -F "${x}.pid"
if
-f "${DIR}/${x}.avi" &&
-f "${DIR}/${x}.wav"; then
ffmpeg -i "${DIR}/${x}.avi" -i "${DIR}/${x}.wav" -c:v copy -c:a copy "${DIR}/${x}.mkv" && rm -f "${DIR}/${x}".{avi,pid,wav}
fi
done <<< "${PIDS}"
# if motion isn't running, kill arecord process if it is running
if ! pgrep -f "sudo nohup motion"; then sudo pkill -9 -f "arecord -f cd -r 22050 -D plughw:2,0"; fi
--
WikiGuest - 30 Jun 2022
Building upon all the comments and solutions, I created a couple scripts and it works perfectly.
## motion.conf
movie_filename %m-%d-%Y_%H:%M:%S
on_event_start /bin/bash /usr/bin/audiorecord.sh %m-%d-%Y_%H:%M:%S
on_event_end /bin/bash /usr/bin/audiokill.sh
#################################
# /usr/bin/audiorecord
#################################
#!/bin/bash
AUDIO=$1
DIR=/dir/to/motion/videos
if pgrep -f "arecord"; then sudo pkill -9 -f "arecord -f cd -r 22050 -D plughw:2,0"; fi
arecord -f cd -r 22050 -D plughw:2,0 ${DIR}/${AUDIO}.wav &
PID=${BASHPID}
echo "${PID}" > "${DIR}/${AUDIO}.pid"
#################################
# audiokill.sh
#################################
#!/bin/bash
DIR=/dir/to/motion/videos
PIDS=$(find ${DIR} -type f -iname "*.pid" -printf "%f\n" | cut -d. -f1)
while read -r x; do
pgrep -F "${x}.pid" && sudo pkill -9 -F "${x}.pid"
if
-f "${DIR}/${x}.avi" &&
-f "${DIR}/${x}.wav"; then
ffmpeg -i "${DIR}/${x}.avi" -i "${DIR}/${x}.wav" -c:v copy -c:a copy "${DIR}/${x}.mkv" && rm -f "${DIR}/${x}".{avi,pid,wav}
fi
done <<< "${PIDS}"
# if motion isn't running, kill arecord process if it is running
if ! pgrep -f "sudo nohup motion"; then sudo pkill -9 -f "arecord -f cd -r 22050 -D plughw:2,0"; fi
###############################
--
WikiGuest - 30 Jun 2022
hello
--
WikiGuest - 14 Mar 2023