channel-worker 2.5.11 → 2.5.12

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "channel-worker",
3
- "version": "2.5.11",
3
+ "version": "2.5.12",
4
4
  "description": "Channel Manager worker daemon — runs on remote machines to execute video pipeline jobs",
5
5
  "main": "lib/daemon.js",
6
6
  "bin": {
@@ -515,8 +515,41 @@ async function run({ page, payload, log }) {
515
515
  await jitter(page, 800);
516
516
 
517
517
  // 5) The KEY step — set the video file.
518
- log('info', `[yt-pw] setInputFiles(video)…`);
519
- await page.locator(S.fileInput).setInputFiles(videoPath);
518
+ //
519
+ // Playwright's setInputFiles() over connectOverCDP caps at 50MB. Real
520
+ // shorts are 100–300MB. Bypass via in-browser fetch: the browser pulls
521
+ // the file directly from our media server (CORS-open on redrop) and we
522
+ // assign the resulting Blob to the input through DataTransfer. The CDP
523
+ // channel never carries the bytes. Falls back to Playwright's native
524
+ // setInputFiles if the browser fetch fails (small files, missing URL).
525
+ log('info', `[yt-pw] setInputFiles(video) via in-browser fetch (bypass CDP 50MB cap)…`);
526
+ let injected = false;
527
+ if (video_url) {
528
+ try {
529
+ injected = await page.evaluate(async ({ url, selector }) => {
530
+ const r = await fetch(url, { credentials: 'omit' });
531
+ if (!r.ok) throw new Error(`fetch ${r.status}`);
532
+ const blob = await r.blob();
533
+ if (!blob || !blob.size) throw new Error('empty blob');
534
+ const fname = (url.split('?')[0].split('/').pop()) || 'video.mp4';
535
+ const file = new File([blob], fname, { type: blob.type || 'video/mp4' });
536
+ const inputs = Array.from(document.querySelectorAll(selector));
537
+ const input = inputs.find((el) => /video/i.test(el.accept || '')) || inputs[0];
538
+ if (!input) throw new Error('input not found');
539
+ const dt = new DataTransfer();
540
+ dt.items.add(file);
541
+ input.files = dt.files;
542
+ input.dispatchEvent(new Event('change', { bubbles: true }));
543
+ return true;
544
+ }, { url: video_url, selector: S.fileInput });
545
+ log('info', `[yt-pw] in-browser fetch upload OK`);
546
+ } catch (e) {
547
+ log('warn', `[yt-pw] in-browser fetch upload failed: ${String(e.message || e).slice(0, 160)} — falling back to Playwright setInputFiles`);
548
+ }
549
+ }
550
+ if (!injected) {
551
+ await page.locator(S.fileInput).setInputFiles(videoPath);
552
+ }
520
553
  log('info', `[yt-pw] file set; waiting for the metadata form to appear…`);
521
554
 
522
555
  // 6) Wait for the Title field to be ready (Studio renders it as the file