11import { setTimeout } from 'node:timers/promises' ;
2- import { exec } from 'node:child_process' ;
2+ import { spawn } from 'node:child_process' ;
3+ import { randomUUID } from 'node:crypto' ;
4+ import { tmpdir } from 'node:os' ;
5+ import { join } from 'node:path' ;
36
47export async function screencast ( page , options ) {
58 const { scale, output, selector, windowWidth, windowHeight } = options ;
@@ -29,8 +32,12 @@ export async function screencast(page, options) {
2932 }
3033 } , selector ) ;
3134
35+ let pathFile = options . mp4
36+ ? join ( tmpdir ( ) , randomUUID ( ) + '.webm' )
37+ : output ;
38+
3239 const recorder = await page . screencast ( {
33- path : output ,
40+ path : pathFile ,
3441 crop,
3542 } ) ;
3643
@@ -39,7 +46,7 @@ export async function screencast(page, options) {
3946
4047 if ( options . mp4 ) {
4148 try {
42- return await webmToMp4 ( output ) ;
49+ return await webmToMp4 ( pathFile , output ) ;
4350 } catch ( e ) {
4451 throw e ;
4552 }
@@ -48,14 +55,16 @@ export async function screencast(page, options) {
4855 return output ;
4956}
5057
51- function webmToMp4 ( input ) {
52- const output = input . replace ( '.webm' , '.mp4' ) ;
58+ function webmToMp4 ( input , output ) {
5359 return new Promise ( ( resolve , reject ) => {
54- exec ( `echo -y | ffmpeg -i ${ input } -c:v copy ${ output } ` , ( err , stdout , stderr ) => {
55- if ( err ) {
56- reject ( err ) ;
57- } else {
60+ const ffmpeg = spawn ( 'ffmpeg' , [ '-i' , input , '-c:v' , 'copy' , output ] ) ;
61+ ffmpeg . stdin . write ( 'y\n' ) ;
62+ ffmpeg . stdin . end ( ) ;
63+ ffmpeg . on ( 'close' , code => {
64+ if ( code === 0 ) {
5865 resolve ( output ) ;
66+ } else {
67+ reject ( new Error ( `error: record failed, ffmpeg exited with code ${ code } ` ) ) ;
5968 }
6069 } ) ;
6170 } ) ;
0 commit comments