Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
44 changes: 9 additions & 35 deletions images/chromium-headful/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -177,42 +177,17 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
apt-get update && \
apt-get -y upgrade && \
apt-get --no-install-recommends -y install \
gpg \
gpg-agent \
# UI Requirements
xvfb \
xterm \
xdotool \
scrot \
imagemagick \
sudo \
mutter \
# Python/pyenv reqs
build-essential \
libssl-dev \
zlib1g-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev \
curl \
git \
libncursesw5-dev \
xz-utils \
tk-dev \
libxml2-dev \
libxmlsec1-dev \
libffi-dev \
liblzma-dev \
# Network tools
net-tools \
netcat \
# PPA req
software-properties-common && \
# Userland apps
sudo add-apt-repository ppa:mozillateam/ppa && \
sudo apt-get --no-install-recommends -y install \
x11-apps \
tint2 \
curl \
wget \
xz-utils \
xdg-utils \
libvulkan1 \
fontconfig \
Expand Down Expand Up @@ -254,7 +229,6 @@ RUN apt-get update && \

# install ffmpeg manually since the version available in apt is from the 4.x branch due to #drama.
COPY --from=ffmpeg-downloader /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg
COPY --from=ffmpeg-downloader /usr/local/bin/ffprobe /usr/local/bin/ffprobe

# runtime
ENV USERNAME=root
Expand All @@ -263,13 +237,13 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
set -eux; \
apt-get update; \
apt-get --no-install-recommends -y install \
wget ca-certificates python2 supervisor xclip xdotool unclutter \
wget ca-certificates supervisor xclip xdotool unclutter \
pulseaudio dbus-x11 xserver-xorg-video-dummy \
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; \
#
# install libxcvt0 (not available in debian:bullseye)
ARCH=$(dpkg --print-architecture); \
Expand All @@ -291,12 +265,11 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
chown $USERNAME /var/log/neko/ /tmp/runtime-$USERNAME; \
chown -R $USERNAME:$USERNAME /home/$USERNAME;

# sqlite3 for debugging the cookies file; runtime libs are chrome-for-testing's listed deb.deps.
# runtime libs are chrome-for-testing's listed deb.deps.
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
apt-get update -y && \
apt-get --no-install-recommends -y install \
sqlite3 \
libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 \
libcups2 libdbus-1-3 libdrm2 libgbm1 libglib2.0-0 libgtk-3-0 \
libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 \
Expand Down Expand Up @@ -333,8 +306,9 @@ RUN set -eux; \
ln -sf /usr/local/lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack; \
fi

# Install TypeScript, Playwright, Patchright, esbuild globally
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm install -g typescript playwright-core patchright esbuild
# Install Playwright, Patchright, esbuild globally (esbuild is required at
# runtime by playwright-daemon.js for TypeScript transformation)
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm install -g playwright-core patchright esbuild

# Pre-install openssh-server and websocat for faster SSH setup via kernel CLI.
# Only installed, NOT configured: no host keys, no custom config, service not enabled.
Expand Down
11 changes: 4 additions & 7 deletions images/chromium-headless/image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
apt-get -yqq --no-install-recommends install \
ca-certificates \
curl \
build-essential \
libssl-dev \
git \
gpg \
gpg-agent \
dbus \
dbus-x11 \
Expand All @@ -159,7 +157,6 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
fonts-noto-cjk \
fonts-noto-color-emoji \
fonts-nanum \
software-properties-common \
supervisor; \
fc-cache -f

Expand Down Expand Up @@ -191,7 +188,6 @@ COPY shared/chromium-policies/managed/policy.json /etc/chromium/policies/managed

# Install FFmpeg (latest static build) for the recording server
COPY --from=ffmpeg-downloader /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg
COPY --from=ffmpeg-downloader /usr/local/bin/ffprobe /usr/local/bin/ffprobe

# Remove upower to prevent spurious D-Bus activations and logs
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
Expand All @@ -209,8 +205,9 @@ RUN set -eux; \
ln -sf /usr/local/lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack; \
fi

# Install TypeScript, Playwright, Patchright, esbuild globally
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm install -g typescript playwright-core patchright esbuild
# Install Playwright, Patchright, esbuild globally (esbuild is required at
# runtime by playwright-daemon.js for TypeScript transformation)
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm install -g playwright-core patchright esbuild

# Pre-install openssh-server and websocat for faster SSH setup via kernel CLI.
# Only installed, NOT configured: no host keys, no custom config, service not enabled.
Expand Down
60 changes: 30 additions & 30 deletions server/e2e/e2e_recording_audio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,41 +449,41 @@ func mp4Durations(t *testing.T, data []byte) (float64, float64) {
recordingPath := filepath.Join(t.TempDir(), "recording.mp4")
require.NoError(t, os.WriteFile(recordingPath, data, 0o644), "failed to write recording for duration analysis")

// Decode the first audio stream to null; ffmpeg reports the container
// duration from the input header and the decoded audio length as the final
// time= progress value. ffprobe is intentionally not shipped in the image.
out, err := exec.Command(
"docker", "run", "--rm",
"-v", recordingPath+":/tmp/recording.mp4:ro",
"--entrypoint", "ffprobe",
"--entrypoint", "ffmpeg",
headfulImage,
"-v", "error",
"-show_entries", "format=duration",
"-show_entries", "stream=codec_type,duration",
"-of", "json",
"/tmp/recording.mp4",
"-hide_banner",
"-i", "/tmp/recording.mp4",
"-map", "0:a:0",
"-f", "null",
"-",
).CombinedOutput()
require.NoError(t, err, "failed to probe recording durations: %s", string(out))

var probe struct {
Streams []struct {
CodecType string `json:"codec_type"`
Duration string `json:"duration"`
} `json:"streams"`
Format struct {
Duration string `json:"duration"`
} `json:"format"`
}
require.NoError(t, json.Unmarshal(out, &probe), "failed to parse ffprobe output")
require.NoError(t, err, "failed to analyze recording durations: %s", string(out))

formatDuration, err := strconv.ParseFloat(probe.Format.Duration, 64)
require.NoError(t, err, "failed to parse format duration")
formatMatch := regexp.MustCompile(`Duration: (\d+):(\d+):(\d+(?:\.\d+)?)`).FindStringSubmatch(string(out))
require.Len(t, formatMatch, 4, "failed to find container duration in ffmpeg output: %s", string(out))
formatDuration := hmsToSeconds(t, formatMatch[1], formatMatch[2], formatMatch[3])

for _, stream := range probe.Streams {
if stream.CodecType != "audio" {
continue
}
audioDuration, err := strconv.ParseFloat(stream.Duration, 64)
require.NoError(t, err, "failed to parse audio duration")
return formatDuration, audioDuration
}
t.Fatal("ffprobe did not report an audio stream")
return 0, 0
timeMatches := regexp.MustCompile(`time=(\d+):(\d+):(\d+(?:\.\d+)?)`).FindAllStringSubmatch(string(out), -1)
require.NotEmpty(t, timeMatches, "failed to find audio duration in ffmpeg output: %s", string(out))
last := timeMatches[len(timeMatches)-1]
audioDuration := hmsToSeconds(t, last[1], last[2], last[3])

return formatDuration, audioDuration
}

func hmsToSeconds(t *testing.T, h, m, s string) float64 {
t.Helper()
hours, err := strconv.ParseFloat(h, 64)
require.NoError(t, err, "failed to parse hours")
minutes, err := strconv.ParseFloat(m, 64)
require.NoError(t, err, "failed to parse minutes")
seconds, err := strconv.ParseFloat(s, 64)
require.NoError(t, err, "failed to parse seconds")
return hours*3600 + minutes*60 + seconds
}
Loading