kettek/dox/linux_desktop_camera_captur...

86 lines
4.7 KiB
Plaintext

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
X11 Desktop + Camera Capture with ffmpeg
````````````````````````````````````````````````
This document is my minimalistic approach to recording my X11 desktop and camera simultaneously on Linux. The ``ffmpeg`` commands in this document use mouse following, as my multi-monitor setup is rather large and leaves some dead-space. Additionally, we want minimal processing, but not enormous files -- hence, we use x264 with minimal, near-lossless, encoding. Finally, we want to record at one frame per second so we can effectively timelapse 60 seconds into 1 second at 60 frames per second.
Do not expect a UI or anything of the sort. This is a hands-on approach using shell scripting. I prefer this.
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Desktop Recording: The Command
````````````````````````````````
The basic command we want to issue is:
#ffmpeg -f x11grab -follow_mouse 428 -draw_mouse 1 -r 1 -video_size 1280x720 -i :0.0 -vcodec libx264 -preset ultrafast -qp 0 my_file.mkv
However, we will want to activate this command indirectly via a script that will be activated by the window manager or ``xbindkeys``. Additionally, we will want some audible indicator of starting and stopping.
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Desktop Recording: The Script
````````````````````````````````
To make this script work, we will: have the file, ``~/.record_poll`` act as both the ``stdin`` redirection for ``ffmpeg`` and as a check for if we are recording. Our capture directory is assumed to exist at ``~/capture/``.
##!/bin/bash
#if [ -f ~/.record_poll ];
#then
# echo 'q' > ~/.record_poll
#else
# touch ~/.record_poll
# date=`date +%Y-%m-%d`
# play /usr/share/sounds/freedesktop/stereo/device-added.oga
# <~/.record_poll ffmpeg -f x11grab -follow_mouse 428 -draw_mouse 1 -r 1 -video_size 1280x720 -i :0.0 -vcodec libx264 -preset ultrafast -qp 0 ~/capture/$date/900_`date +%s`.mkv 2>>~/.record_log
# rm ~/.record_poll
# play /usr/share/sounds/freedesktop/stereo/device-removed.oga
#fi
To test this, open two terminals. Run ``record`` in one to start, then run ``record`` in the other to stop -- or use one terminal and append ``&`` to ``record``.
Alternatively, you could issue a SIGINT or SIGTERM to ffmpeg ((pkill -SIGINT ffmpeg)) to stop rather than polling a file. This behavior seems to vary depending on your ``ffmpeg`` version, so I used a more universal and safe method.
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Camera Recording: The Command
````````````````````````````````
This command is similar to Desktop Recording, but uses the v4l device as the input. This __will__ vary depending on your camera setup.
#ffmpeg -f v4l2 -input_format mjpeg -r 5 -video_size 640x360 -i /dev/video0 -c:v copy -acodec null my_file.avi
Some technical notes must be made here. For this entire operation I wanted to avoid all unneeded CPU usage, so as to leave the actual desktop activity unhindered. As a result, I am using the camera's built-in encoding abilities to produce an mjpeg stream and almost no cost to the CPU. However, web cameras vary greatly in their capabilities, in terms of minimum and maximum framerate, built-in encoding, and video sizes. To get a basic listing of supported settings for your ``/dev/video0`` device, run:
#ffmpeg -f v4l2 -list_formats -all -i /dev/video0
To get extending information on FPS settings:
#v4l2-ctl --list-formats-ext
Finally, in the case of my camera, it only allowed a minimum of 5 frames per second - more than what I needed. To compensate, I had to run post-proccessing to drop the unneeded frames:
#ffmpeg -i my_file.avi -r 1 my_file_1fps.avi
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Camera Recording: The Script
````````````````````````````````
This script follows the exact order of the Desktop Recording:
##!/bin/bash
#if [ -f ~/.camera_poll ];
#then
# echo 'q' > ~/.camera_poll
#else
# touch ~/.camera_poll
# date=`date +%Y-%m-%d`
# play /usr/share/sounds/freedesktop/stereo/device-added.oga
# <~/.camera_poll ffmpeg -f v4l2 -input_format mjpeg -r 5 -video_size 640x360 -i /dev/video0 -c:v copy -acodec null my_file.avi ~/capture/$date/camera_`data +%s`.avi 2>>~/.camera_log
# rm ~/.camera_poll
# play /usr/share/sounds/freedesktop/stereo/device-removed.oga
#fi
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
The Meta Script
````````````````````````````````
To finally tie them together, we just run them at (almost) the same time via a bash script:
##!/bin/bash
#~/bin/rec_camera &
#~/bin/rec_desktop &
Issue this command to start/stop recording as you wish. One note: You could combine these three scripts into one script or even use ffmpeg to pre-embed the camera recording into the desktop recording with some additional CPU usage.