画面録画テスト
このテストは、ヘッド付きブラウザセッションをMP4ファイルに録画することで、VNC/ブラウザスタック全体を検証します。以下の項目を証明します:
- Xvfb が起動しており、
:99で接続を受け付けている - Chromium が仮想ディスプレイ上でヘッド付きモードで起動できる
- ffmpeg がx11grabを使用してディスプレイをキャプチャできる
- 生成された MP4 が有効で再生可能な動画である
動作の仕組み
Section titled “動作の仕組み”- Xディスプレイが準備完了するまで
xdpyinfo -display :99をポーリングします(エントリポイントと同じパターン) - 10 fpsでディスプレイを録画するffmpegを開始します
- Playwrightの
sync_apiを使用してヘッド付きChromiumを起動します https://example.com(3秒間の一時停止)に移動し、次にhttps://httpbin.org(3秒間の一時停止)に移動します- MP4のクリーンな最終処理のためにffmpegにSIGTERMを送信します
- 出力パスとファイルサイズを報告します
以下を vnc-browser-test.py としてコンテナ内に保存するか、このリポジトリの docs/tests/ ディレクトリからコピーしてください:
#!/usr/bin/env python3"""VNC/browser stack integration test.
Proves that Xvfb, headed Chromium (via Playwright), and ffmpeg screenrecording all work together inside the devcontainer by recording abrowser navigating to two websites and producing an MP4 video.
Usage: python3 vnc-browser-test.py [output_path]Default output: /tmp/recording.mp4"""
import osimport signalimport subprocessimport sysimport time
DISPLAY = os.environ.get("DISPLAY", ":99")DEFAULT_OUTPUT = "/tmp/recording.mp4"RESOLUTION = "1280x1024"FRAMERATE = "10"XVFB_TIMEOUT = 50 # iterations (~5 s at 0.1 s each)SITES = [ ("https://example.com", 3), ("https://httpbin.org", 3),]
def wait_for_xvfb(): """Poll xdpyinfo until the X display is ready (mirrors entrypoint.sh).""" print(f"Waiting for Xvfb on {DISPLAY} ...") for i in range(XVFB_TIMEOUT): result = subprocess.run( ["xdpyinfo", "-display", DISPLAY], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) if result.returncode == 0: print(f" Display ready after {i * 0.1:.1f}s") return time.sleep(0.1) sys.exit(f"ERROR: Xvfb display {DISPLAY} not ready after {XVFB_TIMEOUT * 0.1:.1f}s")
def start_recording(output_path): """Start ffmpeg x11grab recording and return the process.""" cmd = [ "ffmpeg", "-y", "-f", "x11grab", "-video_size", RESOLUTION, "-framerate", FRAMERATE, "-i", f"{DISPLAY}.0", "-c:v", "libx264", "-preset", "ultrafast", "-pix_fmt", "yuv420p", output_path, ] print(f"Starting ffmpeg recording -> {output_path}") return subprocess.Popen( cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, )
def stop_recording(proc): """Send SIGTERM and wait for ffmpeg to finalize the MP4.""" print("Stopping ffmpeg ...") proc.send_signal(signal.SIGTERM) try: proc.wait(timeout=10) except subprocess.TimeoutExpired: proc.kill() proc.wait()
def browse_sites(): """Launch headed Chromium via Playwright and visit each site.""" from playwright.sync_api import sync_playwright # noqa: PLC0415
with sync_playwright() as pw: browser = pw.chromium.launch( headless=False, args=[ "--no-sandbox", "--disable-gpu", f"--display={DISPLAY}", ], ) page = browser.new_page(viewport={"width": 1280, "height": 1024})
for url, pause in SITES: print(f" Navigating to {url} ...") try: page.goto(url, timeout=15000) except Exception as exc: # noqa: BLE001 print(f" Warning: navigation error ({exc}), continuing") time.sleep(pause)
browser.close()
def main(): output_path = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_OUTPUT
wait_for_xvfb()
ffmpeg = start_recording(output_path) # Give ffmpeg a moment to initialize before browser activity time.sleep(1)
try: browse_sites() finally: stop_recording(ffmpeg)
if os.path.isfile(output_path): size = os.path.getsize(output_path) print(f"\nSUCCESS: {output_path} ({size:,} bytes)") else: sys.exit(f"ERROR: output file not created: {output_path}")
if __name__ == "__main__": main()テストの実行
Section titled “テストの実行”python3 vnc-browser-test.py /tmp/recording.mp4podman run --rm \ -v $(pwd)/output:/output \ ghcr.io/f5-sales-demo/devcontainer:latest \ python3 vnc-browser-test.py /output/recording.mp4期待される出力
Section titled “期待される出力”Waiting for Xvfb on :99 ... Display ready after 0.3sStarting ffmpeg recording -> /tmp/recording.mp4 Navigating to https://example.com ... Navigating to https://httpbin.org ...Stopping ffmpeg ...
SUCCESS: /tmp/recording.mp4 (1,234,567 bytes)MP4には、fluxboxデスクトップ上で両方のウェブサイトをレンダリングしているChromiumウィンドウが表示されるはずです。ffplay、vlc で再生するか、コンテナからダウンロードして確認してください。
| 症状 | 考えられる原因 |
|---|---|
Xvfb display :99 not ready | Xvfbが起動していない — エントリポイントがVNCスタックを実行したか確認してください |
ffmpeg: x11grab error | ディスプレイの不一致、またはffmpegにx11grabサポートがない |
Playwright launch error | Chromiumがインストールされていない、または --no-sandbox が不足している |
| MP4が0バイト | ffmpegが書き込み前にkillされた — SIGTERMの処理を確認してください |