• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

luttje / videobrew / 8171994845

06 Mar 2024 12:24PM UTC coverage: 25.12% (-19.2%) from 44.313%
8171994845

Pull #25

github

web-flow
Merge 792373961 into 00419a58c
Pull Request #25: Feature/install playwright

356 of 537 branches covered (66.29%)

Branch coverage included in aggregate %.

18 of 93 new or added lines in 7 files covered. (19.35%)

1730 existing lines in 23 files now uncovered.

2003 of 8854 relevant lines covered (22.62%)

461.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/cli/src/rendering/record-frames.ts
UNCOV
1
import { Browser, chromium, Page, PageScreenshotOptions } from 'playwright';
×
UNCOV
2
import { inform } from '../utils/logging.js';
×
UNCOV
3
import chalk from 'chalk';
×
UNCOV
4
import { VideoAppSetup } from '@videobrew/client';
×
UNCOV
5

×
UNCOV
6
type RecordingResult = {
×
UNCOV
7
  width: number,
×
UNCOV
8
  height: number,
×
UNCOV
9
  framerate: number,
×
UNCOV
10
  frameCount: number,
×
UNCOV
11
  frameFiles: string[],
×
UNCOV
12
}
×
UNCOV
13

×
UNCOV
14
type FrameProgressCallback = (currentFrame: number, totalFrames: number) => void;
×
UNCOV
15

×
UNCOV
16
export function getExtensionByQuality(quality: number) {
×
UNCOV
17
  return quality < 100 ? 'jpeg' : 'png';
×
UNCOV
18
}
×
UNCOV
19

×
UNCOV
20
export async function recordFrames(
×
UNCOV
21
  videoAppUrl: string,
×
UNCOV
22
  framesOutputPath: string,
×
UNCOV
23
  renderQuality: number,
×
UNCOV
24
  onFrameProgress?: FrameProgressCallback,
×
UNCOV
25
): Promise<RecordingResult> {
×
UNCOV
26
  return new Promise(async (resolve) => {
×
UNCOV
27
    const browser = await chromium.launch();
×
UNCOV
28
    const page = await browser.newPage();
×
UNCOV
29

×
UNCOV
30
    page.on('console', (message) => inform(`Video App Browser Log: ${message.text()}`));
×
UNCOV
31
    page.on('pageerror', (message) => inform(`Video App Browser Error: ${message}`, chalk.red));
×
UNCOV
32

×
UNCOV
33
    await page.goto(videoAppUrl, {
×
UNCOV
34
      waitUntil: 'domcontentloaded',
×
UNCOV
35
    });
×
UNCOV
36
    
×
UNCOV
37
    let frame = 0;
×
UNCOV
38
    let frameFiles: string[] = [];
×
UNCOV
39
    let width, height, framerate, frameCount;
×
UNCOV
40
    
×
UNCOV
41
    const setup = <VideoAppSetup>(await page.evaluate(`(async () => {
×
UNCOV
42
      return await window.videobrew.init();
×
UNCOV
43
    })()`));
×
UNCOV
44

×
UNCOV
45
    ({ width, height, framerate, frameCount } = setup);
×
UNCOV
46

×
UNCOV
47
    await page.setViewportSize({ width, height });
×
UNCOV
48

×
UNCOV
49
    for (let i = 0; i < frameCount; i++) {
×
UNCOV
50
      frameFiles.push(await captureFrame(page, frame, framesOutputPath, renderQuality));
×
UNCOV
51

×
UNCOV
52
      onFrameProgress?.(frame, frameCount);
×
UNCOV
53
      frame++;
×
UNCOV
54
    }
×
UNCOV
55

×
UNCOV
56
    teardown(browser);
×
UNCOV
57
    resolve({
×
UNCOV
58
      width,
×
UNCOV
59
      height,
×
UNCOV
60
      framerate,
×
UNCOV
61
      frameCount,
×
UNCOV
62
      frameFiles,
×
UNCOV
63
    });
×
UNCOV
64
  });
×
UNCOV
65
}
×
UNCOV
66

×
UNCOV
67
async function captureFrame(page: Page, frameIndex: number, outputPath: string, renderQuality: number) {
×
UNCOV
68
  await page.evaluate(`(async (frameIndex) => {
×
UNCOV
69
    await window.videobrew.tick(frameIndex);
×
UNCOV
70
  })(${frameIndex})`);
×
UNCOV
71
  
×
UNCOV
72
  const extension = getExtensionByQuality(renderQuality);
×
UNCOV
73
  const output = `${outputPath}/${String(frameIndex).padStart(8, '0')}.${extension}`;
×
UNCOV
74

×
UNCOV
75
  const options: PageScreenshotOptions  = {
×
UNCOV
76
    path: output,
×
UNCOV
77
    fullPage: true,
×
UNCOV
78
    type: extension,
×
UNCOV
79
  };
×
UNCOV
80

×
UNCOV
81
  if (extension === 'jpeg')
×
UNCOV
82
    options.quality = renderQuality;
×
UNCOV
83

×
UNCOV
84
  await page.screenshot(options);
×
UNCOV
85

×
UNCOV
86
  return output;
×
UNCOV
87
}
×
UNCOV
88

×
UNCOV
89
async function teardown(browser: Browser) {
×
UNCOV
90
  await browser.close();
×
UNCOV
91
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc