Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 47 additions & 15 deletions images/chromium-headful/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ RUN apt-get update && \
sudo \
mutter \
x11vnc \
upower \
# Python/pyenv reqs
build-essential \
libssl-dev \
Expand Down Expand Up @@ -102,37 +103,56 @@ RUN set -eux; \
install -m755 /tmp/ffmpeg-*/ffprobe /usr/local/bin/ffprobe; \
rm -rf /tmp/ffmpeg*

# runtime
ENV USERNAME=root
# runtime
ARG KERNEL_USER=kernel
ARG KERNEL_UID=1000
ARG KERNEL_GID=$KERNEL_UID
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
wget ca-certificates python2 supervisor xclip xdotool \
pulseaudio dbus-x11 xserver-xorg-video-dummy \
libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
gstreamer1.0-pulseaudio gstreamer1.0-omx; \
wget ca-certificates python2 supervisor xclip xdotool \
pulseaudio dbus-x11 xserver-xorg-video-dummy \
rtkit \
libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
gstreamer1.0-pulseaudio gstreamer1.0-omx; \
#
# install libxcvt0 (not available in debian:bullseye)
ARCH=$(dpkg --print-architecture); \
wget http://ftp.de.debian.org/debian/pool/main/libx/libxcvt/libxcvt0_0.1.2-1_${ARCH}.deb; \
apt-get install --no-install-recommends ./libxcvt0_0.1.2-1_${ARCH}.deb; \
rm ./libxcvt0_0.1.2-1_${ARCH}.deb; \
#
# create a non-root user and add to all relevant audio groups
groupadd --gid $KERNEL_GID $KERNEL_USER; \
useradd --uid $KERNEL_UID --gid $KERNEL_GID --shell /bin/bash --create-home $KERNEL_USER; \
adduser $KERNEL_USER audio; \
adduser $KERNEL_USER video; \
adduser $KERNEL_USER pulse; \
adduser $KERNEL_USER pulse-access; \
#
# workaround for an X11 problem: http://blog.tigerteufel.de/?p=476
mkdir /tmp/.X11-unix; \
chmod 1777 /tmp/.X11-unix; \
chown $USERNAME /tmp/.X11-unix/; \
chown $KERNEL_USER:$KERNEL_USER /tmp/.X11-unix/; \
#
# make directories for neko
mkdir -p /etc/neko /var/www /var/log/neko \
/tmp/runtime-$USERNAME \
/home/$USERNAME/.config/pulse \
/home/$USERNAME/.local/share/xorg; \
/tmp/runtime-$KERNEL_USER \
# /home/$KERNEL_USER/.config/pulse \
/home/$KERNEL_USER/.config \
/home/$KERNEL_USER/.local/share/xorg; \
chmod 1777 /var/log/neko; \
chown $USERNAME /var/log/neko/ /tmp/runtime-$USERNAME; \
chown -R $USERNAME:$USERNAME /home/$USERNAME; \
chown $KERNEL_USER:$KERNEL_USER /var/log/neko/ /tmp/runtime-$KERNEL_USER; \
chown -R $KERNEL_USER:$KERNEL_USER /home/$KERNEL_USER; \
# chown -R $KERNEL_USER:$KERNEL_USER /home/$KERNEL_USER/.config/pulse /etc/pulse || true; \
chown -R $KERNEL_USER:$KERNEL_USER /etc/pulse || true; \
# Ensure /home/$KERNEL_USER/.config and /home/$KERNEL_USER/.config/pulse are owned by the user and world-writable
chmod 777 /home/$KERNEL_USER/.config || true; \
# chmod 777 /home/$KERNEL_USER/.config/pulse || true; \
# Also ensure /etc/pulse is world-writable for config file access
chmod 777 /etc/pulse || true; \
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/
Expand All @@ -153,11 +173,18 @@ ENV WIDTH=1024
ENV WITHDOCKER=true

COPY xorg.conf /etc/neko/xorg.conf

COPY default.pa /etc/pulse/default.pa
COPY daemon.conf /etc/pulse/daemon.conf
COPY dbus-pulseaudio.conf /etc/dbus-1/system.d/pulseaudio.conf
COPY dbus-mpris.conf /etc/dbus-1/system.d/mpris.conf

COPY neko.yaml /etc/neko/neko.yaml
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
COPY --from=xorg-deps /usr/local/lib/xorg/modules/input/neko_drv.so /usr/lib/xorg/modules/input/neko_drv.so
RUN chown -R $KERNEL_USER:$KERNEL_USER /var/www /etc/neko

COPY image-chromium/ /
COPY ./wrapper.sh /wrapper.sh
Expand All @@ -169,5 +196,10 @@ ENV WITH_KERNEL_IMAGES_API=false
RUN useradd -m -s /bin/bash kernel
RUN cp -r ./user-data /home/kernel/user-data

ENTRYPOINT [ "/wrapper.sh" ]
ENV USER=kernel
ENV XDG_RUNTIME_DIR=/tmp/runtime-kernel
ENV PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native
ENV XDG_CONFIG_HOME=/tmp/.chromium
ENV XDG_CACHE_HOME=/tmp/.chromium

ENTRYPOINT [ "/wrapper.sh" ]
57 changes: 55 additions & 2 deletions images/chromium-headful/client/src/components/video.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div ref="component" class="video">
<div ref="player" class="player">
<div ref="player" class="player" :class="{ 'is-muted': muted }">
<div ref="container" class="player-container">
<video ref="video" playsinline />
<div class="emotes">
Expand Down Expand Up @@ -85,6 +85,19 @@
</template>

<style lang="scss" scoped>
/* KERNEL MODIFICATION: Keyframes for the mute indicator pulse effect */
@keyframes mute-pulse {
0% {
box-shadow: inset 0 0 0 2px rgba(255, 80, 80, 0.2);
}
50% {
box-shadow: inset 0 0 0 2px rgba(255, 80, 80, 0.4);
}
100% {
box-shadow: inset 0 0 0 2px rgba(255, 80, 80, 0.2);
}
}

.video {
width: 100%;
height: 100%;
Expand All @@ -96,6 +109,11 @@
align-items: center;
background: #000;

/* KERNEL MODIFICATION: Style for the mute indicator */
&.is-muted {
animation: mute-pulse 2s infinite;
}

.video-menu {
position: absolute;
right: 20px;
Expand Down Expand Up @@ -259,6 +277,10 @@
private fullscreen = false
private mutedOverlay = true

/* KERNEL MODIFICATION: State flag to ensure unmute happens only once. */
private hasInteracted = false
private unmuteHandler: (() => void) | null = null

get admin() {
return this.$accessor.user.admin
}
Expand Down Expand Up @@ -470,6 +492,23 @@
}
}

/* KERNEL MODIFICATION: Centralized one-time unmute logic. */
_unmuteOnFirstInteraction() {
if (this.hasInteracted || !this.muted) {
return
}

this.hasInteracted = true
this.unmute()
this.$accessor.video.setVolume(100)

// Clean up global listeners if they were set
if (this.unmuteHandler) {
document.documentElement.removeEventListener('mousedown', this.unmuteHandler)
document.documentElement.removeEventListener('keydown', this.unmuteHandler)
}
}

mounted() {
this._container.addEventListener('resize', this.onResize)
this.onVolumeChanged(this.volume)
Expand Down Expand Up @@ -533,12 +572,23 @@
this.$client.sendData('keyup', { key: this.keyMap(key) })
}
this.keyboard.listenTo(this._overlay)

/* KERNEL MODIFICATION: Set up listeners for the first interaction. */
this.unmuteHandler = this._unmuteOnFirstInteraction.bind(this)
document.documentElement.addEventListener('mousedown', this.unmuteHandler, { once: true })
document.documentElement.addEventListener('keydown', this.unmuteHandler, { once: true })
}

beforeDestroy() {
this.observer.disconnect()
this.$accessor.video.setPlayable(false)
/* Guacamole Keyboard does not provide destroy functions */

/* KERNEL MODIFICATION: Clean up listeners on component destruction. */
if (this.unmuteHandler) {
document.documentElement.removeEventListener('mousedown', this.unmuteHandler)
document.documentElement.removeEventListener('keydown', this.unmuteHandler)
}
}

get hasMacOSKbd() {
Expand Down Expand Up @@ -761,6 +811,9 @@
}

onMouseDown(e: MouseEvent) {
/* KERNEL MODIFICATION: Trigger unmute on first video click. */
this._unmuteOnFirstInteraction()

if (!this.hosting) {
this.$emit('control-attempt', e)
}
Expand Down Expand Up @@ -846,4 +899,4 @@
this._overlay.focus()
}
}
</script>
</script>
41 changes: 41 additions & 0 deletions images/chromium-headful/daemon.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# /etc/pulse/daemon.conf - OPTIMIZED FOR LOW-LATENCY WEBRTC

# General settings
daemonize = no
fail = yes
allow-module-loading = yes
high-priority = no
realtime-scheduling = no
exit-idle-time = -1

enable-shm = no
; enable-memfd = yes

# Resource limits (keep as is)
rlimit-fsize = -1
rlimit-data = -1
rlimit-stack = -1
rlimit-core = -1
rlimit-as = -1
rlimit-rss = -1
rlimit-nproc = -1
rlimit-nofile = 256
rlimit-memlock = -1
rlimit-locks = -1
rlimit-sigpending = -1
rlimit-msgqueue = -1
rlimit-nice = 31
rlimit-rtprio = 9
rlimit-rttime = 200000

# Low-latency audio settings
default-sample-format = s16le
default-sample-rate = 48000
alternate-sample-rate = 44100
default-sample-channels = 2
default-channel-map = front-left,front-right
resample-method = speex-float-1

# CRITICAL CHANGES FOR LOW LATENCY
default-fragments = 5
default-fragment-size-msec = 5
27 changes: 27 additions & 0 deletions images/chromium-headful/dbus-mpris.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Allow any user to own the MPRIS service for Chromium and all its media player variants -->
<policy context="default">
<!-- Standard Chromium MPRIS service -->
<allow own_prefix="org.mpris.MediaPlayer2.chromium"/>
<!-- Chromium Snap package variant -->
<allow own_prefix="org.mpris.MediaPlayer2.chromium_chromium"/>
<!-- Chromium Flatpak variant -->
<allow own_prefix="org.mpris.MediaPlayer2.org.chromium.Chromium"/>
<!-- Chromium-browser (Debian/Ubuntu) -->
<allow own_prefix="org.mpris.MediaPlayer2.chromium-browser"/>
<!-- Chromium (generic, fallback) -->
<allow own_prefix="org.mpris.MediaPlayer2.Chromium"/>
<!-- Chrome (in case of Chrome being used) -->
<allow own_prefix="org.mpris.MediaPlayer2.google-chrome"/>
<allow own_prefix="org.mpris.MediaPlayer2.Google-chrome"/>
<allow own_prefix="org.mpris.MediaPlayer2.chrome"/>
<!-- Chromium-based Edge (for completeness) -->
<allow own_prefix="org.mpris.MediaPlayer2.microsoft-edge"/>
<!-- Brave (another Chromium-based browser) -->
<allow own_prefix="org.mpris.MediaPlayer2.brave"/>
<!-- Vivaldi (another Chromium-based browser) -->
<allow own_prefix="org.mpris.MediaPlayer2.vivaldi"/>
</policy>
</busconfig>
27 changes: 27 additions & 0 deletions images/chromium-headful/dbus-pulseaudio.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!--
This file allows the user in the 'pulse', 'pulse-access', or 'audio'
groups to own the PulseAudio D-Bus services.
-->

<!-- Policy for 'pulse' group -->
<policy group="pulse">
<allow own="org.PulseAudio1"/>
<allow own="org.pulseaudio.Server"/>
</policy>

<!-- Policy for 'pulse-access' group -->
<policy group="pulse-access">
<allow own="org.PulseAudio1"/>
<allow own="org.pulseaudio.Server"/>
</policy>

<!-- Policy for 'audio' group -->
<policy group="audio">
<allow own="org.PulseAudio1"/>
<allow own="org.pulseaudio.Server"/>
</policy>

</busconfig>
19 changes: 19 additions & 0 deletions images/chromium-headful/default.pa
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/pulseaudio -nF

### Create virtual output device sink
load-module module-null-sink sink_name=audio_output sink_properties=device.description="Virtual_Audio_Output"

### Create virtual input device sink
load-module module-null-sink sink_name=audio_input sink_properties=device.description="Virtual_Audio_Input"

### Create a virtual audio source linked up to the virtual input device
load-module module-virtual-source source_name=microphone master=audio_input.monitor source_properties=device.description="Virtual_Microphone"

### Allow pulse audio to be accessed via a unix socket
load-module module-native-protocol-unix auth-anonymous=1
# adapting from dockerfile : ENV XDG_RUNTIME_DIR=/tmp/runtime-kernel , PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native
# load-module module-native-protocol-unix socket=/tmp/runtime-kernel/pulse/native auth-anonymous=1


### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
3 changes: 2 additions & 1 deletion images/chromium-headful/run-unikernel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ echo "$CHROMIUM_FLAGS" > "$FLAGS_DIR/flags"
kraft cloud volume rm "$volume_name" || true
kraft cloud volume create -n "$volume_name" -s 16M
# Import the flags directory into the freshly created volume
kraft cloud volume import --image onkernel/utils/volimport:1.0 -s "$FLAGS_DIR" -v "$volume_name"
# kraft cloud volume import --image onkernel/utils/volimport:1.0 -s "$FLAGS_DIR" -v "$volume_name"
kraft cloud volume import -s "$FLAGS_DIR" -v "$volume_name"

# Ensure the temp directory is cleaned up on exit
trap 'rm -rf "$FLAGS_DIR"' EXIT
Expand Down
Loading
Loading