diff --git a/.gitignore b/.gitignore
index 69f77654..9b58eca8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -188,3 +188,12 @@ infra/tests/*
# mise-en-place
.mise.toml
+
+# uv
+.venv/
+env/
+venv/
+
+# sample capture artifacts
+samples/virtual-inputs/feed_capture*.mpegts
+samples/virtual-inputs/feed_capture*.ivf
diff --git a/images/chromium-headful/Dockerfile b/images/chromium-headful/Dockerfile
index 974c733c..ebec06e1 100644
--- a/images/chromium-headful/Dockerfile
+++ b/images/chromium-headful/Dockerfile
@@ -224,12 +224,13 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
apt-get update; \
apt-get --no-install-recommends -y install \
wget ca-certificates python2 supervisor xclip xdotool unclutter \
- pulseaudio dbus-x11 xserver-xorg-video-dummy \
+ pulseaudio dbus-x11 xserver-xorg-video-dummy rtkit upower \
libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 \
x11-xserver-utils \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
- gstreamer1.0-pulseaudio gstreamer1.0-omx; \
+ gstreamer1.0-pulseaudio gstreamer1.0-omx \
+ v4l2loopback-dkms v4l2loopback-utils; \
#
# install libxcvt0 (not available in debian:bullseye)
ARCH=$(dpkg --print-architecture); \
@@ -249,7 +250,8 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
/home/$USERNAME/.local/share/xorg; \
chmod 1777 /var/log/neko; \
chown $USERNAME /var/log/neko/ /tmp/runtime-$USERNAME; \
- chown -R $USERNAME:$USERNAME /home/$USERNAME;
+ chown -R $USERNAME:$USERNAME /home/$USERNAME; \
+ chmod 777 /etc/pulse;
# install chromium and sqlite3 for debugging the cookies file
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
@@ -287,6 +289,10 @@ ENV WITHDOCKER=true
COPY images/chromium-headful/xorg.conf /etc/neko/xorg.conf
COPY images/chromium-headful/neko.yaml /etc/neko/neko.yaml
+COPY images/chromium-headful/default.pa /etc/pulse/default.pa
+COPY images/chromium-headful/daemon.conf /etc/pulse/daemon.conf
+COPY images/chromium-headful/dbus-pulseaudio.conf /etc/dbus-1/system.d/pulseaudio.conf
+COPY images/chromium-headful/dbus-mpris.conf /etc/dbus-1/system.d/mpris.conf
COPY --from=neko /usr/bin/neko /usr/bin/neko
COPY --from=client /src/dist/ /var/www
COPY --from=xorg-deps /usr/local/lib/xorg/modules/drivers/dummy_drv.so /usr/lib/xorg/modules/drivers/dummy_drv.so
@@ -306,6 +312,11 @@ COPY --from=server-builder /out/chromium-launcher /usr/local/bin/chromium-launch
# Copy the Playwright executor runtime
COPY server/runtime/playwright-executor.ts /usr/local/lib/playwright-executor.ts
-RUN useradd -m -s /bin/bash kernel
+RUN useradd -m -s /bin/bash kernel && \
+ usermod -aG audio,video,pulse,pulse-access kernel
+
+# Environment variables for audio
+ENV XDG_RUNTIME_DIR=/tmp/runtime-kernel
+ENV PULSE_SERVER=unix:/tmp/runtime-kernel/pulse/native
ENTRYPOINT [ "/wrapper.sh" ]
diff --git a/images/chromium-headful/client/public/browserconfig.xml b/images/chromium-headful/client/public/browserconfig.xml
index ededce1f..0fd3ece4 100644
--- a/images/chromium-headful/client/public/browserconfig.xml
+++ b/images/chromium-headful/client/public/browserconfig.xml
@@ -3,7 +3,7 @@