Skip to content
Open
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
4 changes: 2 additions & 2 deletions images/chromium-headful/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ COPY --from=xorg-deps /usr/local/lib/xorg/modules/drivers/dummy_drv.so /usr/lib/
COPY --from=xorg-deps /usr/local/lib/xorg/modules/input/neko_drv.so /usr/lib/xorg/modules/input/neko_drv.so

COPY images/chromium-headful/image-chromium/ /
COPY images/chromium-headful/start-pulseaudio.sh /images/chromium-headful/start-pulseaudio.sh
RUN chmod +x /images/chromium-headful/start-pulseaudio.sh
COPY shared/start-pulseaudio.sh /usr/local/bin/start-pulseaudio.sh
RUN chmod +x /usr/local/bin/start-pulseaudio.sh
COPY images/chromium-headful/supervisord.conf /etc/supervisor/supervisord.conf
COPY images/chromium-headful/supervisor/services/ /etc/supervisor/conf.d/services/
COPY shared/envoy/supervisor-envoy.conf /etc/supervisor/conf.d/services/envoy.conf
Expand Down
8 changes: 8 additions & 0 deletions images/chromium-headful/neko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ session:
# needed for legacy API
enabled: false

capture:
audio:
# Capture from the monitor of the recorder's playback sink so live view
# streams the same browser audio that gets recorded. Neko defaults to
# "audio_output.monitor", which does not exist here (our sink is
# KernelOutput), so without this override live view has no audio.
device: "KernelOutput.monitor"

plugins:
enabled: false

Expand Down
13 changes: 0 additions & 13 deletions images/chromium-headful/start-pulseaudio.sh

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[program:kernel-images-api]
command=/bin/bash -lc 'mkdir -p "${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" && PORT="${KERNEL_IMAGES_API_PORT:-10001}" FRAME_RATE="${KERNEL_IMAGES_API_FRAME_RATE:-10}" DISPLAY_NUM="${KERNEL_IMAGES_API_DISPLAY_NUM:-${DISPLAY_NUM:-1}}" MAX_SIZE_MB="${KERNEL_IMAGES_API_MAX_SIZE_MB:-500}" OUTPUT_DIR="${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" LOG_CDP_MESSAGES="${LOG_CDP_MESSAGES:-false}" S2_BASIN="${S2_BASIN:-}" S2_ACCESS_TOKEN="${S2_ACCESS_TOKEN:-}" S2_STREAM="${S2_STREAM:-}" exec /usr/local/bin/kernel-images-api'
command=/bin/bash -lc 'mkdir -p "${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" && PORT="${KERNEL_IMAGES_API_PORT:-10001}" FRAME_RATE="${KERNEL_IMAGES_API_FRAME_RATE:-10}" DISPLAY_NUM="${KERNEL_IMAGES_API_DISPLAY_NUM:-${DISPLAY_NUM:-1}}" MAX_SIZE_MB="${KERNEL_IMAGES_API_MAX_SIZE_MB:-500}" OUTPUT_DIR="${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" RECORD_AUDIO="${KERNEL_IMAGES_API_RECORD_AUDIO:-${RECORD_AUDIO:-true}}" AUDIO_SOURCE="${KERNEL_IMAGES_API_AUDIO_SOURCE:-${AUDIO_SOURCE:-KernelOutput.monitor}}" PULSE_SERVER="${PULSE_SERVER:-unix:/tmp/pulse/native}" PULSE_SINK="${PULSE_SINK:-KernelOutput}" LOG_CDP_MESSAGES="${LOG_CDP_MESSAGES:-false}" S2_BASIN="${S2_BASIN:-}" S2_ACCESS_TOKEN="${S2_ACCESS_TOKEN:-}" S2_STREAM="${S2_STREAM:-}" exec /usr/local/bin/kernel-images-api'
autostart=false
autorestart=true
startsecs=0
Expand Down
4 changes: 2 additions & 2 deletions images/chromium-headful/supervisor/services/pulseaudio.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[program:pulseaudio]
command=/bin/bash -lc '/images/chromium-headful/start-pulseaudio.sh'
command=/bin/bash -lc '/usr/local/bin/start-pulseaudio.sh'
autostart=false
autorestart=false
autorestart=true
startsecs=0
exitcodes=0
stdout_logfile=/var/log/supervisord/pulseaudio
Expand Down
3 changes: 3 additions & 0 deletions images/chromium-headless/image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
gpg-agent \
dbus \
dbus-x11 \
pulseaudio \
xvfb \
x11-utils \
x11-xserver-utils \
Expand Down Expand Up @@ -235,6 +236,8 @@ RUN useradd -m -s /bin/bash kernel
# supervisor start scripts
COPY images/chromium-headless/image/start-xvfb.sh /images/chromium-headless/image/start-xvfb.sh
RUN chmod +x /images/chromium-headless/image/start-xvfb.sh
COPY shared/start-pulseaudio.sh /usr/local/bin/start-pulseaudio.sh
RUN chmod +x /usr/local/bin/start-pulseaudio.sh

# Container entrypoint wrapper (Go binary, replaces wrapper.sh)
COPY --from=server-builder /out/wrapper /wrapper
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[program:kernel-images-api]
command=/bin/bash -lc 'mkdir -p "${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" && PORT="${KERNEL_IMAGES_API_PORT:-10001}" FRAME_RATE="${KERNEL_IMAGES_API_FRAME_RATE:-10}" DISPLAY_NUM="${KERNEL_IMAGES_API_DISPLAY_NUM:-${DISPLAY_NUM:-1}}" MAX_SIZE_MB="${KERNEL_IMAGES_API_MAX_SIZE_MB:-500}" OUTPUT_DIR="${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" LOG_CDP_MESSAGES="${LOG_CDP_MESSAGES:-false}" S2_BASIN="${S2_BASIN:-}" S2_ACCESS_TOKEN="${S2_ACCESS_TOKEN:-}" S2_STREAM="${S2_STREAM:-}" exec /usr/local/bin/kernel-images-api'
command=/bin/bash -lc 'mkdir -p "${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" && PORT="${KERNEL_IMAGES_API_PORT:-10001}" FRAME_RATE="${KERNEL_IMAGES_API_FRAME_RATE:-10}" DISPLAY_NUM="${KERNEL_IMAGES_API_DISPLAY_NUM:-${DISPLAY_NUM:-1}}" MAX_SIZE_MB="${KERNEL_IMAGES_API_MAX_SIZE_MB:-500}" OUTPUT_DIR="${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" RECORD_AUDIO="${KERNEL_IMAGES_API_RECORD_AUDIO:-${RECORD_AUDIO:-true}}" AUDIO_SOURCE="${KERNEL_IMAGES_API_AUDIO_SOURCE:-${AUDIO_SOURCE:-KernelOutput.monitor}}" PULSE_SERVER="${PULSE_SERVER:-unix:/tmp/pulse/native}" PULSE_SINK="${PULSE_SINK:-KernelOutput}" LOG_CDP_MESSAGES="${LOG_CDP_MESSAGES:-false}" S2_BASIN="${S2_BASIN:-}" S2_ACCESS_TOKEN="${S2_ACCESS_TOKEN:-}" S2_STREAM="${S2_STREAM:-}" exec /usr/local/bin/kernel-images-api'
autostart=false
autorestart=true
startsecs=0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[program:pulseaudio]
command=/bin/bash -lc '/usr/local/bin/start-pulseaudio.sh'
autostart=false
autorestart=true
startsecs=0
exitcodes=0
stdout_logfile=/var/log/supervisord/pulseaudio
redirect_stderr=true
2 changes: 2 additions & 0 deletions server/cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ func main() {
FrameRate: &config.FrameRate,
MaxSizeInMB: &config.MaxSizeInMB,
OutputDir: &config.OutputDir,
RecordAudio: &config.RecordAudio,
AudioSource: &config.AudioSource,
}
if err := defaultParams.Validate(); err != nil {
slogger.Error("invalid default recording parameters", "err", err)
Expand Down
2 changes: 2 additions & 0 deletions server/cmd/chromium-launcher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ func main() {
"env",
"DISPLAY=:1",
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket",
"PULSE_SERVER=" + os.Getenv("PULSE_SERVER"),
"PULSE_SINK=" + os.Getenv("PULSE_SINK"),
"XDG_CONFIG_HOME=/home/kernel/.config",
"XDG_CACHE_HOME=/home/kernel/.cache",
"HOME=/home/kernel",
Expand Down
7 changes: 7 additions & 0 deletions server/cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type Config struct {
DisplayNum int `envconfig:"DISPLAY_NUM" default:"1"`
MaxSizeInMB int `envconfig:"MAX_SIZE_MB" default:"500"`
OutputDir string `envconfig:"OUTPUT_DIR" default:"."`
RecordAudio bool `envconfig:"RECORD_AUDIO" default:"false"`
AudioSource string `envconfig:"AUDIO_SOURCE" default:"KernelOutput.monitor"`

// Absolute or relative path to the ffmpeg binary. If empty the code falls back to "ffmpeg" on $PATH.
PathToFFmpeg string `envconfig:"FFMPEG_PATH" default:"ffmpeg"`
Expand Down Expand Up @@ -55,6 +57,8 @@ func (c *Config) LogValue() slog.Value {
slog.Int("display_num", c.DisplayNum),
slog.Int("max_size_mb", c.MaxSizeInMB),
slog.String("output_dir", c.OutputDir),
slog.Bool("record_audio", c.RecordAudio),
slog.String("audio_source", c.AudioSource),
slog.String("ffmpeg_path", c.PathToFFmpeg),
slog.Int("devtools_proxy_port", c.DevToolsProxyPort),
slog.Bool("log_cdp_messages", c.LogCDPMessages),
Expand Down Expand Up @@ -100,6 +104,9 @@ func validate(config *Config) error {
if config.PathToFFmpeg == "" {
return fmt.Errorf("FFMPEG_PATH is required")
}
if config.RecordAudio && config.AudioSource == "" {
return fmt.Errorf("AUDIO_SOURCE is required when RECORD_AUDIO is true")
}
if config.ChromeDriverUpstreamAddr == "" {
return fmt.Errorf("CHROMEDRIVER_UPSTREAM_ADDR is required")
}
Expand Down
16 changes: 16 additions & 0 deletions server/cmd/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ func TestLoad(t *testing.T) {
DisplayNum: 1,
MaxSizeInMB: 500,
OutputDir: ".",
RecordAudio: false,
AudioSource: "KernelOutput.monitor",
PathToFFmpeg: "ffmpeg",
DevToolsProxyPort: 9222,
ScaleToZeroCooldown: time.Second,
Expand All @@ -39,6 +41,8 @@ func TestLoad(t *testing.T) {
"DISPLAY_NUM": "2",
"MAX_SIZE_MB": "250",
"OUTPUT_DIR": "/tmp",
"RECORD_AUDIO": "true",
"AUDIO_SOURCE": "CustomOutput.monitor",
"FFMPEG_PATH": "/usr/local/bin/ffmpeg",
"DEVTOOLS_PROXY_PORT": "9876",
"SCALE_TO_ZERO_COOLDOWN": "5s",
Expand All @@ -51,6 +55,8 @@ func TestLoad(t *testing.T) {
DisplayNum: 2,
MaxSizeInMB: 250,
OutputDir: "/tmp",
RecordAudio: true,
AudioSource: "CustomOutput.monitor",
PathToFFmpeg: "/usr/local/bin/ffmpeg",
DevToolsProxyPort: 9876,
ScaleToZeroCooldown: 5 * time.Second,
Expand All @@ -71,6 +77,8 @@ func TestLoad(t *testing.T) {
DisplayNum: 1,
MaxSizeInMB: 500,
OutputDir: ".",
RecordAudio: false,
AudioSource: "KernelOutput.monitor",
PathToFFmpeg: "ffmpeg",
DevToolsProxyPort: 7777,
ScaleToZeroCooldown: time.Second,
Expand Down Expand Up @@ -114,6 +122,14 @@ func TestLoad(t *testing.T) {
},
wantErr: true,
},
{
name: "missing audio source when recording audio",
env: map[string]string{
"RECORD_AUDIO": "true",
"AUDIO_SOURCE": "",
},
wantErr: true,
},
{
name: "missing chromedriver upstream addr (set to empty)",
env: map[string]string{
Expand Down
1 change: 0 additions & 1 deletion server/cmd/wrapper/chromium.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ func applyHeadlessDefaultFlags() {
"--hide-crash-restore-bubble",
"--hide-scrollbars",
"--metrics-recording-only",
"--mute-audio",
"--no-default-browser-check",
"--no-first-run",
"--no-sandbox",
Expand Down
20 changes: 13 additions & 7 deletions server/cmd/wrapper/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const (
dbusSocket = "/run/dbus/system_bus_socket"
defaultDisplay = ":1"
defaultIntPort = "9223"
pulseSocket = "/tmp/pulse/native"
)

type profile int
Expand Down Expand Up @@ -119,6 +120,15 @@ func main() {
// starts so it captures the env for child services (notably chromium,
// which would otherwise spam autolaunch errors).
_ = os.Setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path="+dbusSocket)
if os.Getenv("PULSE_SERVER") == "" {
_ = os.Setenv("PULSE_SERVER", "unix:"+pulseSocket)
}
if os.Getenv("PULSE_SINK") == "" {
_ = os.Setenv("PULSE_SINK", "KernelOutput")
}
if os.Getenv("AUDIO_SOURCE") == "" {
_ = os.Setenv("AUDIO_SOURCE", "KernelOutput.monitor")
}

// Stale X locks from prior runs.
_ = os.Remove("/tmp/.X1-lock")
Expand Down Expand Up @@ -172,11 +182,13 @@ func main() {
_ = os.WriteFile(filepath.Join(supervisordLogD, "chromium"), nil, 0o644)

browserStart := time.Now()
startAll(xServer, "dbus", "chromedriver", "chromium")
startAll(xServer, "dbus", "chromedriver", "pulseaudio")
waitForX(defaultDisplay, 20*time.Second)
if prof == profileHeadful {
startAll("mutter")
}
waitForSocket(pulseSocket, 10*time.Second)
startAll("chromium")
waitForSocket(dbusSocket, 10*time.Second)
if prof == profileHeadful && webrtc {
startAll("neko")
Expand Down Expand Up @@ -223,12 +235,6 @@ func main() {
identityDone.Sub(identityStart).Truncate(time.Millisecond),
formatProbeDurations(probeDurations))

// Cosmetic + non-critical services come up off the hot path. Headless has
// no audio stack.
if prof == profileHeadful {
go startAll("pulseaudio")
}

// Re-enable scale-to-zero now that the hot path is up — unless the caller
// asked to keep it disabled via ENABLE_STZ=false/0.
if stzManaged {
Expand Down
Loading
Loading