diff --git a/configure.ac b/configure.ac
index 2038fae..d33879c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,7 +56,7 @@ AC_MSG_CHECKING([for GStreamer (needed for recording functionality)])
 if $PKG_CONFIG --exists gstreamer-0.10 '>=' $GSTREAMER_MIN_VERSION ; then
    AC_MSG_RESULT(yes)
    build_recorder=true
-   recorder_modules="gstreamer-0.10 gstreamer-base-0.10 x11"
+   recorder_modules="gstreamer-0.10 gstreamer-base-0.10 clutter-gst-1.0 x11"
    PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes)
 else
    AC_MSG_RESULT(no)
diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
index 55db42a..6582235 100644
--- a/data/org.gnome.shell.gschema.xml.in
+++ b/data/org.gnome.shell.gschema.xml.in
@@ -132,5 +132,31 @@
         changed when recording to a different container format.
       </_description>
     </key>
+    <key name="record-webcam" type="b">
+      <default>false</default>
+      <_summary>Add a webcam overlay to the recording.</_summary>
+      <_description>
+        Whether video from the webcam should be overlaid to the screen
+         capture.
+      </_description>
+    </key>
+    <key name="webcam-opacity" type="i">
+      <default>230</default>
+      <_summary>Opacity of the webcam overlay</_summary>
+      <_description>
+        When recording screencasts it can be useful to have a partially
+         transparent webcam overlay so that the desktop area is not completely
+        hidden in the recording.
+      </_description>
+    </key>
+    <key name="webcam-device" type="s">
+      <default>/dev/video0</default>
+      <_summary>Video device for webcam overlay</_summary>
+      <_description>
+        This is the video device used for the webcam overlay feature. Even
+         though it will most likely be a webcam, in reality it can be any 
+         video device that you wish to overlay on the screencast.
+      </_description>
+    </key>
   </schema>
 </schemalist>
diff --git a/js/ui/main.js b/js/ui/main.js
index b159c93..8548154 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -113,6 +113,10 @@ function _initRecorder() {
             // read the parameters from GSettings always in case they have changed
             recorder.set_framerate(recorderSettings.get_int('framerate'));
             recorder.set_filename('shell-%d%u-%c.' + recorderSettings.get_string('file-extension'));
+            recorder.set_record_webcam(recorderSettings.get_boolean('record-webcam'));
+            recorder.set_webcam_opacity(recorderSettings.get_int('webcam-opacity'));
+            recorder.set_webcam_device(recorderSettings.get_string('webcam-device'));
+
             let pipeline = recorderSettings.get_string('pipeline');
 
             if (!pipeline.match(/^\s*$/))
diff --git a/src/shell-recorder.c b/src/shell-recorder.c
index 9df14d3..d077ac1 100644
--- a/src/shell-recorder.c
+++ b/src/shell-recorder.c
@@ -15,6 +15,7 @@
 
 #include <clutter/x11/clutter-x11.h>
 #include <X11/extensions/Xfixes.h>
+#include <clutter-gst/clutter-gst.h>
 
 typedef enum {
   RECORDER_STATE_CLOSED,
@@ -55,6 +56,8 @@ struct _ShellRecorder {
   int xfixes_event_base;
 
   CoglHandle *recording_icon; /* icon shown while playing */
+  ClutterActor *webcam_overlay;
+  GstElement *webcam_pipeline;
 
   cairo_surface_t *cursor_image;
   int cursor_hot_x;
@@ -65,6 +68,10 @@ struct _ShellRecorder {
   int framerate;
   char *pipeline_description;
   char *filename;
+  gboolean record_webcam;
+  int webcam_opacity;
+  char *webcam_device;
+ 
   gboolean filename_has_count; /* %c used: handle pausing differently */
 
   /* We might have multiple pipelines that are finishing encoding
@@ -100,6 +107,12 @@ static void recorder_set_pipeline (ShellRecorder *recorder,
                                    const char    *pipeline);
 static void recorder_set_filename (ShellRecorder *recorder,
                                    const char    *filename);
+static void recorder_set_record_webcam (ShellRecorder *recorder,
+                                   gboolean doit);
+static void recorder_set_webcam_opacity (ShellRecorder *recorder,
+                                   int opacity);
+static void recorder_set_webcam_device (ShellRecorder *recorder,
+                                   const char    *device);
 
 static void recorder_pipeline_set_caps (RecorderPipeline *pipeline);
 static void recorder_pipeline_closed   (RecorderPipeline *pipeline);
@@ -109,7 +122,10 @@ enum {
   PROP_STAGE,
   PROP_FRAMERATE,
   PROP_PIPELINE,
-  PROP_FILENAME
+  PROP_FILENAME,
+  PROP_RECORD_WEBCAM,
+  PROP_WEBCAM_OPACITY,
+  PROP_WEBCAM_DEVICE
 };
 
 G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT);
@@ -156,10 +172,19 @@ G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT);
  */
 #define DEFAULT_MEMORY_TARGET (512*1024)
 
+/* The default opacity level for the picture-in-picture webcam overlay 
+ * so that the desktop area is not completely hidden in the screencast
+ * recording. 
+ *
+ * Opacity values range from 0 to 255. 
+ */
+#define DEFAULT_WEBCAM_OPACITY (230)
+
 /* Create an emblem to show at the lower-left corner of the stage while
  * recording. The emblem is drawn *after* we record the frame so doesn't
  * show up in the frame.
  */
+
 static CoglHandle *
 create_recording_icon (void)
 {
@@ -207,6 +232,52 @@ create_recording_icon (void)
   return texture;
 }
 
+/* TODO: how do we detect the webcam aspect ratio ? */
+#define webcam_aspect_ratio (4.0/3.0)
+
+/* TODO: hardcoded webcam overlay dimensions */
+#define webcam_height (recorder->stage_height/6)
+#define webcam_width (webcam_aspect_ratio*webcam_height)
+
+static void
+create_webcam_overlay (ShellRecorder *recorder)
+{
+  GstElement *videosink, *v4l2src, *ffmpegcolor;
+
+  recorder->webcam_overlay = clutter_texture_new();
+  clutter_actor_show (recorder->webcam_overlay);
+
+  clutter_container_add_actor (CLUTTER_CONTAINER (recorder->stage),
+                               recorder->webcam_overlay);
+
+/* TODO: hardcoded webcam overlay positioning on the stage */
+  clutter_actor_set_position(recorder->webcam_overlay,
+                             recorder->stage_width - 1.3*webcam_width,
+                             recorder->stage_height - 1.3*webcam_height);
+  clutter_actor_set_size(recorder->webcam_overlay, webcam_width, webcam_height);
+  clutter_actor_set_opacity(recorder->webcam_overlay, recorder->webcam_opacity);
+
+  videosink = clutter_gst_video_sink_new ((ClutterTexture *) recorder->webcam_overlay);
+  v4l2src = gst_element_factory_make ("v4l2src", NULL);
+  g_object_set(G_OBJECT(v4l2src), "device", recorder->webcam_device, NULL);
+  ffmpegcolor = gst_element_factory_make ("ffmpegcolorspace", NULL);
+
+  recorder->webcam_pipeline = gst_pipeline_new ("webcam");
+  gst_bin_add_many (GST_BIN (recorder->webcam_pipeline), v4l2src,
+                    ffmpegcolor, videosink, NULL);
+  gst_element_link_many (v4l2src, ffmpegcolor, videosink, NULL);
+
+  gst_element_set_state(recorder->webcam_pipeline, GST_STATE_PLAYING);
+}
+
+static void
+delete_webcam_overlay (ShellRecorder *recorder)
+{
+  gst_element_set_state(recorder->webcam_pipeline, GST_STATE_NULL);
+  gst_object_unref (recorder->webcam_pipeline);
+  clutter_container_remove_actor (CLUTTER_CONTAINER (recorder->stage), recorder->webcam_overlay);
+}
+
 static guint
 get_memory_target (void)
 {
@@ -861,6 +932,10 @@ recorder_set_stage (ShellRecorder *recorder,
       clutter_stage_ensure_current (stage);
 
       recorder_get_initial_cursor_position (recorder);
+
+      if (recorder->webcam_overlay)
+        clutter_container_add_actor (CLUTTER_CONTAINER (recorder->stage), recorder->webcam_overlay);
+
     }
 }
 
@@ -917,6 +992,45 @@ recorder_set_filename (ShellRecorder *recorder,
   g_object_notify (G_OBJECT (recorder), "filename");
 }
 
+static void recorder_set_record_webcam (ShellRecorder *recorder,
+                                   gboolean doit)
+{
+  if (doit == recorder->record_webcam)
+    return;
+
+  recorder->record_webcam = doit;
+
+  g_object_notify (G_OBJECT (recorder), "record-webcam");
+}
+
+static void recorder_set_webcam_opacity (ShellRecorder *recorder,
+                                   int opacity)
+{
+  if (opacity == recorder->webcam_opacity)
+    return;
+
+  recorder->webcam_opacity = opacity;
+
+  g_object_notify (G_OBJECT (recorder), "webcam-opacity");
+}
+
+static void recorder_set_webcam_device (ShellRecorder *recorder,
+                                   const char    *device)
+{
+  if (device == recorder->webcam_device ||
+      (device && recorder->webcam_device && strcmp (recorder->webcam_device, device) == 0))
+    return;
+
+  if (recorder->webcam_device)
+    g_free (recorder->webcam_device);
+
+  recorder->webcam_device = g_strdup (device);
+
+  g_object_notify (G_OBJECT (recorder), "webcam-device");
+
+}
+
+
 static void
 shell_recorder_set_property (GObject      *object,
                              guint         prop_id,
@@ -939,6 +1053,15 @@ shell_recorder_set_property (GObject      *object,
     case PROP_FILENAME:
       recorder_set_filename (recorder, g_value_get_string (value));
       break;
+    case PROP_WEBCAM_DEVICE:
+      recorder_set_webcam_device (recorder, g_value_get_string (value));
+      break;
+    case PROP_WEBCAM_OPACITY:
+      recorder_set_webcam_opacity (recorder, g_value_get_int (value));
+      break;
+    case PROP_RECORD_WEBCAM:
+      recorder_set_record_webcam (recorder, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -967,6 +1090,15 @@ shell_recorder_get_property (GObject         *object,
     case PROP_FILENAME:
       g_value_set_string (value, recorder->filename);
       break;
+    case PROP_WEBCAM_DEVICE:
+      g_value_set_string (value, recorder->webcam_device);
+      break;
+    case PROP_WEBCAM_OPACITY:
+      g_value_set_int ( value, recorder->webcam_opacity);
+      break;
+    case PROP_RECORD_WEBCAM:
+      g_value_set_boolean ( value, recorder->record_webcam);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1015,6 +1147,29 @@ shell_recorder_class_init (ShellRecorderClass *klass)
                                                         "The filename template to use for output files",
                                                         NULL,
                                                         G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_RECORD_WEBCAM,
+                                   g_param_spec_boolean ("recordwebcam",
+                                                         "RecordWebcam",
+                                                         "Add a webcam overlay to the recording",
+                                                         FALSE,
+                                                         G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_WEBCAM_OPACITY,
+                                   g_param_spec_int ("webcam-opacity",
+                                                      "WebcamOpacity",
+                                                      "Opacity of the webcam overlay",
+                                                      0,
+                                                      255,
+                                                      DEFAULT_WEBCAM_OPACITY,
+                                                      G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_WEBCAM_DEVICE,
+                                   g_param_spec_string ("webcam-device",
+                                                        "WebcamDevice",
+                                                        "Video device for webcam overlay",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
 }
 
 /* Sets the GstCaps (video format, in this case) on the stream
@@ -1631,6 +1786,59 @@ shell_recorder_set_pipeline (ShellRecorder *recorder,
 }
 
 /**
+ * shell_recorder_set_record_webcam:
+ * @recorder: the #ShellRecorder
+ * @doit: a boolean value. True if a webcam overlay should be recorded 
+ *          in the screencast. False, otherwise.
+ *
+ * Whether video from the webcam should be overlaid to the screen capture.
+ *
+ */
+void
+shell_recorder_set_record_webcam (ShellRecorder *recorder,
+                             gboolean doit)
+{
+  g_return_if_fail (SHELL_IS_RECORDER (recorder));
+
+  recorder_set_record_webcam (recorder, doit);
+}
+
+/**
+ * shell_recorder_set_webcam_opacity:
+ * @recorder: the #ShellRecorder
+ * @opacity: Opacity of the webcam overlay in the range from 0 to 255
+ *
+ * When recording screencasts it can be useful to have a partially
+ * transparent webcam overlay so that the desktop area is not completely
+ * hidden in the recording.
+ *
+ */
+void
+shell_recorder_set_webcam_opacity (ShellRecorder *recorder,
+                             int opacity)
+{
+  g_return_if_fail (SHELL_IS_RECORDER (recorder));
+  g_return_if_fail (opacity>=0 && opacity<=255);
+
+  recorder_set_webcam_opacity (recorder, opacity);
+}
+
+/**
+ * shell_recorder_set_webcam_device:
+ * @recorder: the #ShellRecorder
+ * @device: string indicating the video device for the webcam overlay
+ *
+ */
+void
+shell_recorder_set_webcam_device (ShellRecorder *recorder,
+                             const char    *device)
+{
+  g_return_if_fail (SHELL_IS_RECORDER (recorder));
+
+  recorder_set_webcam_device (recorder, device);
+}
+
+/**
  * shell_recorder_record:
  * @recorder: the #ShellRecorder
  *
@@ -1656,6 +1864,9 @@ shell_recorder_record (ShellRecorder *recorder)
   g_return_val_if_fail (recorder->stage != NULL, FALSE);
   g_return_val_if_fail (recorder->state != RECORDER_STATE_RECORDING, FALSE);
 
+  if (recorder->record_webcam)
+    create_webcam_overlay(recorder);
+
   if (recorder->current_pipeline)
     {
       /* Adjust the start time so that the times in the stream ignore the
@@ -1704,6 +1915,9 @@ shell_recorder_pause (ShellRecorder *recorder)
   g_return_if_fail (SHELL_IS_RECORDER (recorder));
   g_return_if_fail (recorder->state == RECORDER_STATE_RECORDING);
 
+  if (recorder->webcam_overlay)
+    delete_webcam_overlay(recorder);
+
   recorder_remove_update_pointer_timeout (recorder);
   /* We want to record one more frame since some time may have
    * elapsed since the last frame
diff --git a/src/shell-recorder.h b/src/shell-recorder.h
index fe96c5b..6c61b4f 100644
--- a/src/shell-recorder.h
+++ b/src/shell-recorder.h
@@ -36,6 +36,13 @@ void               shell_recorder_set_filename (ShellRecorder *recorder,
 						const char    *filename);
 void               shell_recorder_set_pipeline (ShellRecorder *recorder,
 						const char    *pipeline);
+void               shell_recorder_set_record_webcam (ShellRecorder *recorder,
+						gboolean  doit);
+void               shell_recorder_set_webcam_opacity (ShellRecorder *recorder,
+						int opacity);
+void               shell_recorder_set_webcam_device (ShellRecorder *recorder,
+						const char    *device);
+
 gboolean           shell_recorder_record       (ShellRecorder *recorder);
 void               shell_recorder_close        (ShellRecorder *recorder);
 void               shell_recorder_pause        (ShellRecorder *recorder);
