straight_to_video 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- // straight-to-video@0.0.8 vendored by the straight_to_video gem
1
+ // straight-to-video@0.0.9 vendored by the straight_to_video gem
2
2
  // straight-to-video - https://github.com/searlsco/straight-to-video
3
3
 
4
4
  // ----- External imports -----
@@ -170,62 +170,88 @@ async function selectVideoEncoderConfig ({ width, height, fps }) {
170
170
  return { codecId: 'avc', config: supA.config }
171
171
  }
172
172
 
173
- async function encodeVideo ({ file, srcMeta, plan, onProgress }) {
174
- const w = srcMeta.w
175
- const h = srcMeta.h
176
- const durationCfr = Number(srcMeta.duration)
177
- const long = Math.max(w, h)
178
- const scale = Math.min(1, MAX_LONG_SIDE / Math.max(2, long))
179
- const targetWidth = Math.max(2, Number(plan?.width) || Math.round(w * scale))
180
- const targetHeight = Math.max(2, Number(plan?.height) || Math.round(h * scale))
181
-
182
- const targetFps = Math.max(1, Number(plan?.fps) || await determineTargetFps(file, { width: w, height: h }))
183
- const step = 1 / Math.max(1, targetFps)
184
- const frames = Math.max(1, Math.floor(durationCfr / step))
173
+ function shouldDecodeViaVideoElement () {
174
+ return (navigator?.vendor || '').includes('Apple')
175
+ }
185
176
 
186
- const output = new Output({ format: new Mp4OutputFormat({ fastStart: 'in-memory' }), target: new BufferTarget() })
187
- const { codecId, config: usedCfg } = await selectVideoEncoderConfig({ width: targetWidth, height: targetHeight, fps: targetFps })
188
- const videoTrack = new EncodedVideoPacketSource(codecId)
189
- output.addVideoTrack(videoTrack, { frameRate: targetFps })
177
+ async function waitForFrameReady (video, budgetMs) {
178
+ if (typeof video.requestVideoFrameCallback !== 'function') return false
179
+ return await new Promise((resolve) => {
180
+ let settled = false
181
+ const to = setTimeout(() => { if (!settled) { settled = true; resolve(false) } }, Math.max(1, budgetMs || 17))
182
+ video.requestVideoFrameCallback(() => { if (!settled) { settled = true; clearTimeout(to); resolve(true) } })
183
+ })
184
+ }
190
185
 
191
- const _warn = console.warn
192
- console.warn = (...args) => {
193
- const m = args && args[0]
194
- if (typeof m === 'string' && m.includes('Unsupported audio codec') && m.includes('apac')) return
195
- _warn.apply(console, args)
196
- }
197
- const audioBuffer = await decodeAudioPCM(file, { duration: durationCfr })
198
- console.warn = _warn
186
+ async function seekOnce (video, time) {
187
+ if (!video) return
188
+ const t = Number.isFinite(time) ? time : 0
189
+ if (Math.abs(video.currentTime - t) < 1e-6) return
190
+ await new Promise((resolve) => {
191
+ const onSeeked = () => {
192
+ video.removeEventListener('seeked', onSeeked)
193
+ resolve()
194
+ }
195
+ video.addEventListener('seeked', onSeeked, { once: true })
196
+ video.currentTime = t
197
+ })
198
+ }
199
199
 
200
- const audioSource = new AudioSampleSource({
201
- codec: 'aac',
202
- bitrate: TARGET_AUDIO_BITRATE,
203
- bitrateMode: 'constant',
204
- numberOfChannels: TARGET_AUDIO_CHANNELS,
205
- sampleRate: TARGET_AUDIO_SR,
206
- onEncodedPacket: (_packet, meta) => {
207
- const aot = 2; const idx = 3; const b0 = (aot << 3) | (idx >> 1); const b1 = ((idx & 1) << 7) | (TARGET_AUDIO_CHANNELS << 3)
208
- meta.decoderConfig = { codec: 'mp4a.40.2', numberOfChannels: TARGET_AUDIO_CHANNELS, sampleRate: TARGET_AUDIO_SR, description: new Uint8Array([b0, b1]) }
200
+ async function encodeFramesViaVideoElement ({ file, durationCfr, step, frames, canvas, ctx, ve, onProgress }) {
201
+ const url = URL.createObjectURL(file)
202
+ const v = document.createElement('video')
203
+ v.muted = true; v.preload = 'auto'; v.playsInline = true
204
+ await new Promise((resolve, reject) => {
205
+ const onLoaded = () => {
206
+ v.removeEventListener('loadedmetadata', onLoaded)
207
+ v.removeEventListener('error', onError)
208
+ resolve()
209
+ }
210
+ const onError = () => {
211
+ v.removeEventListener('loadedmetadata', onLoaded)
212
+ v.removeEventListener('error', onError)
213
+ reject(new Error('video load failed'))
214
+ }
215
+ v.addEventListener('loadedmetadata', onLoaded)
216
+ v.addEventListener('error', onError)
217
+ v.src = url
218
+ try {
219
+ v.load()
220
+ } catch (err) {
221
+ console.warn('straight-to-video: video.load() threw; continuing without explicit load()', err)
209
222
  }
210
223
  })
211
- output.addAudioTrack(audioSource)
212
224
 
213
- await output.start()
225
+ for (let i = 0; i < frames; i++) {
226
+ const t = i * step
227
+ const drawTime = Math.min(Math.max(0, t + (step * 0.5)), Math.max(0.000001, durationCfr - 0.000001))
228
+ await seekOnce(v, drawTime)
229
+ const budgetMs = Math.min(34, Math.max(17, Math.round(step * 1000)))
230
+ const presented = await waitForFrameReady(v, budgetMs)
231
+ if (!presented && i === 0) {
232
+ const nudge = Math.min(step * 0.25, 0.004)
233
+ const target = Math.min(drawTime + nudge, Math.max(0.000001, durationCfr - 0.000001))
234
+ await seekOnce(v, target)
235
+ }
214
236
 
215
- let codecDesc = null
216
- const pendingPackets = []
217
- const ve = new VideoEncoder({
218
- output: (chunk, meta) => {
219
- if (!codecDesc && meta?.decoderConfig?.description) codecDesc = meta.decoderConfig.description
220
- pendingPackets.push({ chunk })
221
- },
222
- error: () => {}
223
- })
224
- ve.configure(usedCfg)
237
+ ctx.drawImage(v, 0, 0, canvas.width, canvas.height)
238
+ const vf = new VideoFrame(canvas, { timestamp: Math.round(t * 1e6), duration: Math.round(step * 1e6) })
239
+ ve.encode(vf, { keyFrame: i === 0 })
240
+ vf.close()
225
241
 
226
- const canvas = document.createElement('canvas'); canvas.width = targetWidth; canvas.height = targetHeight
227
- const ctx = canvas.getContext('2d', { alpha: false })
242
+ if (typeof onProgress === 'function') {
243
+ try {
244
+ onProgress(Math.min(1, (i + 1) / frames))
245
+ } catch (err) {
246
+ console.warn('straight-to-video: onProgress callback threw; ignoring error', err)
247
+ }
248
+ }
249
+ }
228
250
 
251
+ URL.revokeObjectURL(url)
252
+ }
253
+
254
+ async function encodeFramesViaVideoSampleSink ({ file, durationCfr, step, frames, canvas, ctx, ve, onProgress }) {
229
255
  const input = new Input({ source: new BlobSource(file), formats: ALL_FORMATS })
230
256
  const tracks = await input.getTracks()
231
257
  const video = tracks.find(t => typeof t.isVideoTrack === 'function' && t.isVideoTrack())
@@ -284,10 +310,80 @@ async function encodeVideo ({ file, srcMeta, plan, onProgress }) {
284
310
  const vf = new VideoFrame(canvas, { timestamp: Math.round(t * 1e6), duration: Math.round(step * 1e6) })
285
311
  ve.encode(vf, { keyFrame: i === 0 })
286
312
  vf.close()
313
+
314
+ if (typeof onProgress === 'function') {
315
+ try {
316
+ onProgress(Math.min(1, (i + 1) / frames))
317
+ } catch (err) {
318
+ console.warn('straight-to-video: onProgress callback threw; ignoring error', err)
319
+ }
320
+ }
321
+
287
322
  i++
288
323
  }
289
324
  if (typeof prev.close === 'function') prev.close()
290
325
  }
326
+ }
327
+
328
+ async function encodeVideo ({ file, srcMeta, plan, onProgress }) {
329
+ const w = srcMeta.w
330
+ const h = srcMeta.h
331
+ const durationCfr = Number(srcMeta.duration)
332
+ const long = Math.max(w, h)
333
+ const scale = Math.min(1, MAX_LONG_SIDE / Math.max(2, long))
334
+ const targetWidth = Math.max(2, Number(plan?.width) || Math.round(w * scale))
335
+ const targetHeight = Math.max(2, Number(plan?.height) || Math.round(h * scale))
336
+
337
+ const targetFps = Math.max(1, Number(plan?.fps) || await determineTargetFps(file, { width: w, height: h }))
338
+ const step = 1 / Math.max(1, targetFps)
339
+ const frames = Math.max(1, Math.floor(durationCfr / step))
340
+
341
+ const output = new Output({ format: new Mp4OutputFormat({ fastStart: 'in-memory' }), target: new BufferTarget() })
342
+ const { codecId, config: usedCfg } = await selectVideoEncoderConfig({ width: targetWidth, height: targetHeight, fps: targetFps })
343
+ const videoTrack = new EncodedVideoPacketSource(codecId)
344
+ output.addVideoTrack(videoTrack, { frameRate: targetFps })
345
+
346
+ const _warn = console.warn
347
+ console.warn = (...args) => {
348
+ const m = args && args[0]
349
+ if (typeof m === 'string' && m.includes('Unsupported audio codec') && m.includes('apac')) return
350
+ _warn.apply(console, args)
351
+ }
352
+ const audioBuffer = await decodeAudioPCM(file, { duration: durationCfr })
353
+ console.warn = _warn
354
+
355
+ const audioSource = new AudioSampleSource({
356
+ codec: 'aac',
357
+ bitrate: TARGET_AUDIO_BITRATE,
358
+ bitrateMode: 'constant',
359
+ numberOfChannels: TARGET_AUDIO_CHANNELS,
360
+ sampleRate: TARGET_AUDIO_SR,
361
+ onEncodedPacket: (_packet, meta) => {
362
+ const aot = 2; const idx = 3; const b0 = (aot << 3) | (idx >> 1); const b1 = ((idx & 1) << 7) | (TARGET_AUDIO_CHANNELS << 3)
363
+ meta.decoderConfig = { codec: 'mp4a.40.2', numberOfChannels: TARGET_AUDIO_CHANNELS, sampleRate: TARGET_AUDIO_SR, description: new Uint8Array([b0, b1]) }
364
+ }
365
+ })
366
+ output.addAudioTrack(audioSource)
367
+
368
+ await output.start()
369
+
370
+ let codecDesc = null
371
+ const pendingPackets = []
372
+ const ve = new VideoEncoder({
373
+ output: (chunk, meta) => {
374
+ if (!codecDesc && meta?.decoderConfig?.description) codecDesc = meta.decoderConfig.description
375
+ pendingPackets.push({ chunk })
376
+ },
377
+ error: () => {}
378
+ })
379
+ ve.configure(usedCfg)
380
+
381
+ const canvas = document.createElement('canvas'); canvas.width = targetWidth; canvas.height = targetHeight
382
+ const ctx = canvas.getContext('2d', { alpha: false })
383
+
384
+ await (shouldDecodeViaVideoElement()
385
+ ? encodeFramesViaVideoElement({ file, durationCfr, step, frames, canvas, ctx, ve, onProgress })
386
+ : encodeFramesViaVideoSampleSink({ file, durationCfr, step, frames, canvas, ctx, ve, onProgress }))
291
387
  await ve.flush()
292
388
 
293
389
  const muxCount = Math.min(frames, pendingPackets.length)
data/index.js CHANGED
@@ -169,62 +169,88 @@ async function selectVideoEncoderConfig ({ width, height, fps }) {
169
169
  return { codecId: 'avc', config: supA.config }
170
170
  }
171
171
 
172
- async function encodeVideo ({ file, srcMeta, plan, onProgress }) {
173
- const w = srcMeta.w
174
- const h = srcMeta.h
175
- const durationCfr = Number(srcMeta.duration)
176
- const long = Math.max(w, h)
177
- const scale = Math.min(1, MAX_LONG_SIDE / Math.max(2, long))
178
- const targetWidth = Math.max(2, Number(plan?.width) || Math.round(w * scale))
179
- const targetHeight = Math.max(2, Number(plan?.height) || Math.round(h * scale))
180
-
181
- const targetFps = Math.max(1, Number(plan?.fps) || await determineTargetFps(file, { width: w, height: h }))
182
- const step = 1 / Math.max(1, targetFps)
183
- const frames = Math.max(1, Math.floor(durationCfr / step))
172
+ function shouldDecodeViaVideoElement () {
173
+ return (navigator?.vendor || '').includes('Apple')
174
+ }
184
175
 
185
- const output = new Output({ format: new Mp4OutputFormat({ fastStart: 'in-memory' }), target: new BufferTarget() })
186
- const { codecId, config: usedCfg } = await selectVideoEncoderConfig({ width: targetWidth, height: targetHeight, fps: targetFps })
187
- const videoTrack = new EncodedVideoPacketSource(codecId)
188
- output.addVideoTrack(videoTrack, { frameRate: targetFps })
176
+ async function waitForFrameReady (video, budgetMs) {
177
+ if (typeof video.requestVideoFrameCallback !== 'function') return false
178
+ return await new Promise((resolve) => {
179
+ let settled = false
180
+ const to = setTimeout(() => { if (!settled) { settled = true; resolve(false) } }, Math.max(1, budgetMs || 17))
181
+ video.requestVideoFrameCallback(() => { if (!settled) { settled = true; clearTimeout(to); resolve(true) } })
182
+ })
183
+ }
189
184
 
190
- const _warn = console.warn
191
- console.warn = (...args) => {
192
- const m = args && args[0]
193
- if (typeof m === 'string' && m.includes('Unsupported audio codec') && m.includes('apac')) return
194
- _warn.apply(console, args)
195
- }
196
- const audioBuffer = await decodeAudioPCM(file, { duration: durationCfr })
197
- console.warn = _warn
185
+ async function seekOnce (video, time) {
186
+ if (!video) return
187
+ const t = Number.isFinite(time) ? time : 0
188
+ if (Math.abs(video.currentTime - t) < 1e-6) return
189
+ await new Promise((resolve) => {
190
+ const onSeeked = () => {
191
+ video.removeEventListener('seeked', onSeeked)
192
+ resolve()
193
+ }
194
+ video.addEventListener('seeked', onSeeked, { once: true })
195
+ video.currentTime = t
196
+ })
197
+ }
198
198
 
199
- const audioSource = new AudioSampleSource({
200
- codec: 'aac',
201
- bitrate: TARGET_AUDIO_BITRATE,
202
- bitrateMode: 'constant',
203
- numberOfChannels: TARGET_AUDIO_CHANNELS,
204
- sampleRate: TARGET_AUDIO_SR,
205
- onEncodedPacket: (_packet, meta) => {
206
- const aot = 2; const idx = 3; const b0 = (aot << 3) | (idx >> 1); const b1 = ((idx & 1) << 7) | (TARGET_AUDIO_CHANNELS << 3)
207
- meta.decoderConfig = { codec: 'mp4a.40.2', numberOfChannels: TARGET_AUDIO_CHANNELS, sampleRate: TARGET_AUDIO_SR, description: new Uint8Array([b0, b1]) }
199
+ async function encodeFramesViaVideoElement ({ file, durationCfr, step, frames, canvas, ctx, ve, onProgress }) {
200
+ const url = URL.createObjectURL(file)
201
+ const v = document.createElement('video')
202
+ v.muted = true; v.preload = 'auto'; v.playsInline = true
203
+ await new Promise((resolve, reject) => {
204
+ const onLoaded = () => {
205
+ v.removeEventListener('loadedmetadata', onLoaded)
206
+ v.removeEventListener('error', onError)
207
+ resolve()
208
+ }
209
+ const onError = () => {
210
+ v.removeEventListener('loadedmetadata', onLoaded)
211
+ v.removeEventListener('error', onError)
212
+ reject(new Error('video load failed'))
213
+ }
214
+ v.addEventListener('loadedmetadata', onLoaded)
215
+ v.addEventListener('error', onError)
216
+ v.src = url
217
+ try {
218
+ v.load()
219
+ } catch (err) {
220
+ console.warn('straight-to-video: video.load() threw; continuing without explicit load()', err)
208
221
  }
209
222
  })
210
- output.addAudioTrack(audioSource)
211
223
 
212
- await output.start()
224
+ for (let i = 0; i < frames; i++) {
225
+ const t = i * step
226
+ const drawTime = Math.min(Math.max(0, t + (step * 0.5)), Math.max(0.000001, durationCfr - 0.000001))
227
+ await seekOnce(v, drawTime)
228
+ const budgetMs = Math.min(34, Math.max(17, Math.round(step * 1000)))
229
+ const presented = await waitForFrameReady(v, budgetMs)
230
+ if (!presented && i === 0) {
231
+ const nudge = Math.min(step * 0.25, 0.004)
232
+ const target = Math.min(drawTime + nudge, Math.max(0.000001, durationCfr - 0.000001))
233
+ await seekOnce(v, target)
234
+ }
213
235
 
214
- let codecDesc = null
215
- const pendingPackets = []
216
- const ve = new VideoEncoder({
217
- output: (chunk, meta) => {
218
- if (!codecDesc && meta?.decoderConfig?.description) codecDesc = meta.decoderConfig.description
219
- pendingPackets.push({ chunk })
220
- },
221
- error: () => {}
222
- })
223
- ve.configure(usedCfg)
236
+ ctx.drawImage(v, 0, 0, canvas.width, canvas.height)
237
+ const vf = new VideoFrame(canvas, { timestamp: Math.round(t * 1e6), duration: Math.round(step * 1e6) })
238
+ ve.encode(vf, { keyFrame: i === 0 })
239
+ vf.close()
224
240
 
225
- const canvas = document.createElement('canvas'); canvas.width = targetWidth; canvas.height = targetHeight
226
- const ctx = canvas.getContext('2d', { alpha: false })
241
+ if (typeof onProgress === 'function') {
242
+ try {
243
+ onProgress(Math.min(1, (i + 1) / frames))
244
+ } catch (err) {
245
+ console.warn('straight-to-video: onProgress callback threw; ignoring error', err)
246
+ }
247
+ }
248
+ }
227
249
 
250
+ URL.revokeObjectURL(url)
251
+ }
252
+
253
+ async function encodeFramesViaVideoSampleSink ({ file, durationCfr, step, frames, canvas, ctx, ve, onProgress }) {
228
254
  const input = new Input({ source: new BlobSource(file), formats: ALL_FORMATS })
229
255
  const tracks = await input.getTracks()
230
256
  const video = tracks.find(t => typeof t.isVideoTrack === 'function' && t.isVideoTrack())
@@ -283,10 +309,80 @@ async function encodeVideo ({ file, srcMeta, plan, onProgress }) {
283
309
  const vf = new VideoFrame(canvas, { timestamp: Math.round(t * 1e6), duration: Math.round(step * 1e6) })
284
310
  ve.encode(vf, { keyFrame: i === 0 })
285
311
  vf.close()
312
+
313
+ if (typeof onProgress === 'function') {
314
+ try {
315
+ onProgress(Math.min(1, (i + 1) / frames))
316
+ } catch (err) {
317
+ console.warn('straight-to-video: onProgress callback threw; ignoring error', err)
318
+ }
319
+ }
320
+
286
321
  i++
287
322
  }
288
323
  if (typeof prev.close === 'function') prev.close()
289
324
  }
325
+ }
326
+
327
+ async function encodeVideo ({ file, srcMeta, plan, onProgress }) {
328
+ const w = srcMeta.w
329
+ const h = srcMeta.h
330
+ const durationCfr = Number(srcMeta.duration)
331
+ const long = Math.max(w, h)
332
+ const scale = Math.min(1, MAX_LONG_SIDE / Math.max(2, long))
333
+ const targetWidth = Math.max(2, Number(plan?.width) || Math.round(w * scale))
334
+ const targetHeight = Math.max(2, Number(plan?.height) || Math.round(h * scale))
335
+
336
+ const targetFps = Math.max(1, Number(plan?.fps) || await determineTargetFps(file, { width: w, height: h }))
337
+ const step = 1 / Math.max(1, targetFps)
338
+ const frames = Math.max(1, Math.floor(durationCfr / step))
339
+
340
+ const output = new Output({ format: new Mp4OutputFormat({ fastStart: 'in-memory' }), target: new BufferTarget() })
341
+ const { codecId, config: usedCfg } = await selectVideoEncoderConfig({ width: targetWidth, height: targetHeight, fps: targetFps })
342
+ const videoTrack = new EncodedVideoPacketSource(codecId)
343
+ output.addVideoTrack(videoTrack, { frameRate: targetFps })
344
+
345
+ const _warn = console.warn
346
+ console.warn = (...args) => {
347
+ const m = args && args[0]
348
+ if (typeof m === 'string' && m.includes('Unsupported audio codec') && m.includes('apac')) return
349
+ _warn.apply(console, args)
350
+ }
351
+ const audioBuffer = await decodeAudioPCM(file, { duration: durationCfr })
352
+ console.warn = _warn
353
+
354
+ const audioSource = new AudioSampleSource({
355
+ codec: 'aac',
356
+ bitrate: TARGET_AUDIO_BITRATE,
357
+ bitrateMode: 'constant',
358
+ numberOfChannels: TARGET_AUDIO_CHANNELS,
359
+ sampleRate: TARGET_AUDIO_SR,
360
+ onEncodedPacket: (_packet, meta) => {
361
+ const aot = 2; const idx = 3; const b0 = (aot << 3) | (idx >> 1); const b1 = ((idx & 1) << 7) | (TARGET_AUDIO_CHANNELS << 3)
362
+ meta.decoderConfig = { codec: 'mp4a.40.2', numberOfChannels: TARGET_AUDIO_CHANNELS, sampleRate: TARGET_AUDIO_SR, description: new Uint8Array([b0, b1]) }
363
+ }
364
+ })
365
+ output.addAudioTrack(audioSource)
366
+
367
+ await output.start()
368
+
369
+ let codecDesc = null
370
+ const pendingPackets = []
371
+ const ve = new VideoEncoder({
372
+ output: (chunk, meta) => {
373
+ if (!codecDesc && meta?.decoderConfig?.description) codecDesc = meta.decoderConfig.description
374
+ pendingPackets.push({ chunk })
375
+ },
376
+ error: () => {}
377
+ })
378
+ ve.configure(usedCfg)
379
+
380
+ const canvas = document.createElement('canvas'); canvas.width = targetWidth; canvas.height = targetHeight
381
+ const ctx = canvas.getContext('2d', { alpha: false })
382
+
383
+ await (shouldDecodeViaVideoElement()
384
+ ? encodeFramesViaVideoElement({ file, durationCfr, step, frames, canvas, ctx, ve, onProgress })
385
+ : encodeFramesViaVideoSampleSink({ file, durationCfr, step, frames, canvas, ctx, ve, onProgress }))
290
386
  await ve.flush()
291
387
 
292
388
  const muxCount = Math.min(frames, pendingPackets.length)
@@ -1,3 +1,3 @@
1
1
  module StraightToVideo
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
data/package-lock.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "straight-to-video",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "straight-to-video",
9
- "version": "0.0.8",
9
+ "version": "0.0.9",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "mediabunny": "^1.24.4"
12
+ "mediabunny": "^1.27.3"
13
13
  },
14
14
  "devDependencies": {
15
- "@playwright/test": "^1.56.1",
15
+ "@playwright/test": "^1.57.0",
16
16
  "busboy": "^1.6.0"
17
17
  },
18
18
  "peerDependencies": {
@@ -33,13 +33,13 @@
33
33
  "peer": true
34
34
  },
35
35
  "node_modules/@playwright/test": {
36
- "version": "1.56.1",
37
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz",
38
- "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==",
36
+ "version": "1.57.0",
37
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz",
38
+ "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==",
39
39
  "dev": true,
40
40
  "license": "Apache-2.0",
41
41
  "dependencies": {
42
- "playwright": "1.56.1"
42
+ "playwright": "1.57.0"
43
43
  },
44
44
  "bin": {
45
45
  "playwright": "cli.js"
@@ -91,9 +91,9 @@
91
91
  }
92
92
  },
93
93
  "node_modules/mediabunny": {
94
- "version": "1.24.4",
95
- "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.24.4.tgz",
96
- "integrity": "sha512-dpWYBPTtMg152yNLXZQ7xb6hsXdYbKp9EuK8qq4npS+SZ08FVc1XHlXYhrOm31T+tUVJKgm95Yaqy69wTpZP9Q==",
94
+ "version": "1.27.3",
95
+ "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.3.tgz",
96
+ "integrity": "sha512-hlzmgzMznp9DhA5fMJKS5yEAyfCUMxAc+DbSPxD4J1J2cYVl1L+pZLndkt5xLlD5aB5eHEnphHMW14ammMlUXg==",
97
97
  "license": "MPL-2.0",
98
98
  "workspaces": [
99
99
  "packages/*"
@@ -108,13 +108,13 @@
108
108
  }
109
109
  },
110
110
  "node_modules/playwright": {
111
- "version": "1.56.1",
112
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz",
113
- "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==",
111
+ "version": "1.57.0",
112
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz",
113
+ "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==",
114
114
  "dev": true,
115
115
  "license": "Apache-2.0",
116
116
  "dependencies": {
117
- "playwright-core": "1.56.1"
117
+ "playwright-core": "1.57.0"
118
118
  },
119
119
  "bin": {
120
120
  "playwright": "cli.js"
@@ -127,9 +127,9 @@
127
127
  }
128
128
  },
129
129
  "node_modules/playwright-core": {
130
- "version": "1.56.1",
131
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz",
132
- "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==",
130
+ "version": "1.57.0",
131
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz",
132
+ "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==",
133
133
  "dev": true,
134
134
  "license": "Apache-2.0",
135
135
  "bin": {
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "straight-to-video",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Browser-based, hardware-accelerated video upload optimization",
5
5
  "type": "module",
6
6
  "exports": {
@@ -15,7 +15,7 @@
15
15
  }
16
16
  },
17
17
  "dependencies": {
18
- "mediabunny": "^1.24.4"
18
+ "mediabunny": "^1.27.3"
19
19
  },
20
20
  "keywords": [
21
21
  "webcodecs",
@@ -41,7 +41,7 @@
41
41
  "test": "script/test"
42
42
  },
43
43
  "devDependencies": {
44
- "@playwright/test": "^1.56.1",
44
+ "@playwright/test": "^1.57.0",
45
45
  "busboy": "^1.6.0"
46
46
  }
47
47
  }