- From: Viktor Shchelochkov via GitHub <sysbot+gh@w3.org>
- Date: Mon, 10 Feb 2025 13:42:09 +0000
- To: public-webrtc-logs@w3.org
> Thanks for a great lib, [@Vanilagy](https://github.com/Vanilagy). Helps a ton! I can confirm that using it with MediaStreamTrackProcessor#getReader works as expected. > > Here's my example (wrapping [@theatrejs](https://github.com/theatrejs)): > > import { createRafDriver, ISheet, val } from '@theatre/core' > import { useRef } from 'react' > import WebMMuxer from 'webm-muxer' > > export const rafDriver = createRafDriver({ name: 'Hubble rAF driver' }) > > export const useRenderer = ({ > sheet, > fps = 30, > width = 1280, > height = 720, > bitrate = 1e6, > }: { > sheet: ISheet > fps?: number > width?: number > height?: number > bitrate?: number > }) => { > const { sequence } = sheet > const duration = val(sequence.pointer.length) > const totalFrames = duration * fps > > // A way for the renderer to signal that the frame has finished drawing > const renderDone = useRef((_a?: unknown) => {}) > const frameReady = () => { > return new Promise((resolve) => (renderDone.current = resolve)) > } > > const captureFrame = () => { > renderDone.current() > } > > const startCapture = async ({ canvas }: { canvas: HTMLCanvasElement }) => { > let i = 0 > > let videoEncoder = new VideoEncoder({ > output: (chunk, meta) => muxer.addVideoChunk(chunk, meta, i * fps * 1000), > error: (e) => console.error(e), > }) > > videoEncoder.configure({ > codec: 'vp09.00.10.08', > width, > height, > bitrate, > bitrateMode: "constant" > }) > > async function encodeFrame(data: VideoFrame) { > const keyFrame = i % 60 === 0 > videoEncoder.encode(data, { keyFrame }) > } > > async function finishEncoding() { > await videoEncoder.flush() > muxer.finalize() > reader.releaseLock() > await fileWritableStream.close() > } > > const fileHandle = await window.showSaveFilePicker({ > suggestedName: `video.webm`, > types: [ > { > description: 'Video File', > accept: { 'video/webm': ['.webm'] }, > }, > ], > }) > > const fileWritableStream = await fileHandle.createWritable() > > const muxer = new WebMMuxer({ > target: fileWritableStream, > video: { > codec: 'V_VP9', > width, > height, > frameRate: fps, > }, > }) > > await sheet.project.ready > const track = canvas.captureStream(0).getVideoTracks()[0] > // @ts-expect-error > const mediaProcessor = new MediaStreamTrackProcessor(track) > const reader = mediaProcessor.readable.getReader() > > for (i = 0; i < totalFrames; i++) { > sequence.position = i / fps > rafDriver.tick(performance.now()) > > console.log(`capturing frame ${i}/${totalFrames} at simtime ${i / fps}`) > > await frameReady() > > // @ts-expect-error > track.requestFrame() > const result = await reader.read() > const frame = result.value > > await encodeFrame(frame) > > frame.close() > } > finishEncoding() > } > > return { startCapture, captureFrame } > } @akre54 solution was almost perfect for me, but Safari, despite what MDN and caniuse.com says, still has not implemented MediaStreamTrackProcessor, so I created this workaround which works perfectly in Safari: ```ts const frame = new VideoFrame(canvas, { timestamp: currentFrame * frameInterval * 1000, duration: frameInterval * 1000, }) ``` In that case you don't even need MediaStreamTrackProcessor at all -- GitHub Notification of comment by VityaSchel Please view or discuss this issue at https://github.com/w3c/mediacapture-record/issues/213#issuecomment-2648025322 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Monday, 10 February 2025 13:42:10 UTC