hwebcam is a simple program that lets you capture a video stream from a uvc-compatible webcam and display it to the screen or save it in Ogg/Theora format. Optionally, audio from the built-in microphone present in many webcams can also be captured and encoded in Vorbis. The resulting Ogg file can be saved and/or streamed through the net using icecast.

These are some of the things you can do with hwebcam:

  1. Capture and display a video in a sdl window
  2. Capture and save a picture every n video frames (or every frame)
  3. Save the captured video stream in Ogg/Theora format to an output file, or send it to stdout
  4. Same as previous point, but also including Vorbis audio

Of course you can do, for example, a and b together, or a and d together.

Note: hwebcam supports capturing from webcams in raw (YUYV) mode, mjpeg mode or jpeg mode using streaming I/O. The images are saved in Portable Pix Map (ppm) format when capturing in raw mode and in jpeg format when capturing in mjpeg/jpeg mode.


hwebcam is released under the GNU GPLv3 license.

How to compile hwebcam

hwebcam is written in C an uses the v4l2 api to access the webcam, along with several external libraries to do the encoding/decoding stuff. Since it is still a relatively simple program, there is no configure script.
In order to compile hwebcam you need:

  1. gcc
  2. make
  3. libsdl (optional)
  4. libtheora 1.1
  5. libasound
  6. libvorbis
  7. libvorbisenc
  8. libjpeg

Under Debian/Ubuntu all the dependencies should be satisfied by installing the following packages:

build-essential libsdl1.2-dev libtheora-dev libasound2-dev libvorbis-dev libvorbisenc2 libjpeg62-dev

You can compile the source file simply with:

$ make

or if you don't need the SDL version, with:

$ make USE_SDL=0

hwebcam uses simd optimizations for some functions on the x86 architecture. To enable those optimization compile hwebcam like this:

$ make ARCH=X86_64

Allowed values of ARCH are: X86_32, X86_64, generic (which is the default).

If you want to clean the build directory just run:

$ make clean

The resulting binary can be put, for example, in /usr/local/bin or can be run from the local directory.

Using hwebcam

You can access the help by running:

$ ./hwebcam -h
hwebcam, ver. 0.48

usage: hwebcam [options]
       -h          print help
       -v          increment verbosity level
Video options:
       -d videodev use video device videodev      (/dev/video0)
       -I input    choose device input            (autodetected)
       -s WxH      choose frame size              (640x400)
       -i fps      choose frame rate              (10)
       -f fmt      choose pixelformat, supported values:
                   yuyv, yuv, mjpeg, jpeg         (yuyv)
       -g          grayscale                      (disabled)
       -t val      save a frame every val seconds (disabled, 0=every frame)
       -e          encode captured stream in ogg/theora/vorbis
       -o ofile    save captured stream in ofile  (capture.ogg, -=stdout)
       -b bitrate  choose theora bitrate in bit/s (200000)
       -q quality  choose theora quality          (0, range=[0-63])
       -w          display stream in a sdl window
Audio options:
       -a          include audio in captured stream
       -D audiodev use audio device audiodev      (hw:0,0)
       -c channels choose number of channels      (1)
       -r rate     choose sampling rate           (32000)
       -B bitrate  choose vorbis bitrate in bit/s (48000)
       -Q quality  choose vorbis quality          (0.1, range=[-0.1 - 1.0])

The values in parentheses on the right are the default values.
Here's some command line examples:


Screenshot of hwebcam in action:


The values on the statistic bar on the bottom have the following meanings:


And this is a video realized with my Logitech C200 using hwebcam (for those of you who are wondering what that circuit is, it's a simple astable multivibrator with a nominal frequency of 0.7Hz realized with a 555 chip):

Live streaming HOWTO

Simple Streaming-howto using hwebcam + oggfwd + icecast2 (tested on Ubuntu 10.04):

  1. Install icecast2 and oggfwd with:

    sudo apt-get install icecast2 oggfwd

  2. Edit /etc/icecast2/icecast.xml and change:
    • limits/burst-size: 131072 (only for high bitrate streams, otherwise 65536 is fine)
    • authentication/passwords
    • hostname
    • listen-socket/port (if you need a different port)
  3. Edit /etc/default/icecast2 and set ENABLE=true
  4. Start the icecast2 server with:

    sudo /etc/init.d/icecast2 start

  5. Start capturing with hwebcam and send the stream to the server using oggfwd (you need to substitute PORT and PASS with the correct values in the command below):

    ./hwebcam -d /dev/video1 -s 352x288 -i 10 -w -e -o - | oggfwd -n Webcam -d "Webcam test" localhost PORT PASS /webcam.ogg

    This will capture a 352x288@10fps stream from /dev/video1, display it on a sdl window, encode the stream to Ogg/Theora and dump the encoded file to stdout. oggfwd will read from stdin and forward the stream to the server using the mountpoint /webcam.ogg, setting name and description of the stream to "Webcam" and "Webcam test" respectively.
  6. Fire up a Ogg/Theora compatible browser (like Firefox or Chromium) and point it to:


    you should be able to see the streaming video. Or, you can of course use your favourite video player, like totem, vlc, ffplay or mplayer to watch the stream.

Tested webcams


The following versions of hwebcam are available for download. Please note that hwebcam is still in development and it should be considered beta software. We recommend you to download the latest version.


version 0.48:

	* Encoding support for image heights not multiple of 16
	* jpeg.c: abort if fill_input_buffer() is called

version 0.47:

	* Discard damaged jpeg images
	* output_message() method in jpeg error handler
	* Two levels of status bar (-v and -v -v)
	* Simpler buffer overrun handling
	* Added common.{h,c} (message printing utilities)
	* Lots of cosmetics fixes

version 0.46:

	* Option -I to select v4l2 device input
	* Option -f to select pixelformat
	* Algorithm to maintain a/v sync by dropping/duplicating frames
	* V4L2_PIX_FMT_YUV420 support
	* Use posix_memalign() to allocate memory for ycbcrbuf
	* Better buffer overrun handling

version 0.45:

	* Error manager for libjpeg
	* Support for fractional fps
	* Acquisition from v4l2 devices, like TV cards, that support a standard (PAL, NTSC, etc)
	* Flush stream at the end of muxer_write()
	* Embed program version in stream comments

version 0.44:

	* Use multiplication instead of division in int16_t -> float conversion loop
	* buffer overrun handling
	* audio.{h,c}: added playback support
	* Faster and simpler audio_find_peak()

version 0.43:

	* Grayscale video support
	* Added yuyv422_to_y8() (c, mmxext, sse2)
	* Makefile: better CFLAGS handling
	* Fixed license header

version 0.42:

	* yuyv422_to_yuv420p() simd optimization for x86_{32,64} (mmxext, sse2)
	* Runtime simd extensions detection for x86 cpus
	* Makefile support for ARCH=X86_{32,64}
	* More precise yuv444->yuv422 conversion in jpeg_decompress
	* More precise average calculation on yuyv422_to_yuv420p_c()
	* Fix memory allocation in ycbcrbuf
	* Stats: print only nonzero fields
	* Stats: time spent in sdl code
	* Stats: audio ring buffer fill state

version 0.41:

	* V4L2_PIX_FMT_JPEG support
	* Use only one variable i_rows_c in yuyv422_to_yuv420p()
	* Initialize max to correct value in audio_find_peak()

version 0.40:

	* mjpeg decoding via libjpeg
	* V4L2_PIX_FMT_MJPEG support
	* Save frames in jpeg format when capturing in mjpeg
	* yuyv422_to_rgb24() optimization
	* Bugfix: prevent infinite loop in muxer_write() on i32 due to fp comparison
	* README update

version 0.33:

	* yuyv422_to_yuv420p() optimization
	* Bugfix: fflush(stderr)
	* Makefile: introduce USE_SDL, we now have only one makefile
	* README update

version 0.32:

	* Add audio_find_peak()
	* Use only one fprintf in usage()
	* Move stats printing at the end of the main loop

version 0.31:

	* Add muxer to produce valid ogg files
	* When encoding in Theora, make sure image sizes are multiple of 16
	* Print audio/video info only when verbose >= 2

version 0.30:

	* Vorbis audio encoding
	* poll() support and general rework
	* verbose levels
	* Lots of cosmetics
	* Makefile, README and STREAMING-HOWTO update
	* Add MSGPREFIX in video.c
	* Add video_{start,stop}_streaming()

version 0.23:

	* Check sigaction return value
	* Bugfix in sdl caption_string when actual_fps = 0
	* Add th_*_clear()
	* Use unsigned int for width/height in video_init()

version 0.22:

	* Bugfix in yuyv422_to_yuv420p()
	* More robust fps calculation
	* Better support for duplicate frames at fps/2 and fps/4
	* Cosmetics: HWebcam -> hwebcam

version 0.21:

	* Ogg stream serialno = time(NULL)
	* keyframe_granule_shift = 6
	* Use ogg_stream_pageout for the headers and then ogg_stream_flush

version 0.20:

	* Theora video encoding

version 0.11:

	* Move normal output to stderr

version 0.10:

	* Initial release

Valid XHTML 1.0 Strict

Copyright (C) 2011 Giorgio Vazzana