T-HUB/apps/media-worker/scripts/test-windows-worker.md
hacklab 8f01765df3 feat: adapt T-HUB features — folders schema, Instagram connector, outreach contacts, media RLS force
From the hacklab/T-HUB fork (diverged at a6843e9):
- 046_file_folders: folder trees (group + personal scope, RLS forced,
  workspace-immutability trigger) + created_by on chat_media_archive
- Instagram connector wired into connect + publishing
- outreach contacts: per-collective DM tracking (todo/sent/replied/declined),
  RLS forced, role-scoped permissions, audit without message text,
  migration renumbered 041→047
- FORCE row-level security on media_assets
The J1 api agent's folder service/controller work continues separately.
2026-10-18 10:40:45 +00:00

5.6 KiB

Native Windows transcode worker: manual checks on moxexleyhp1

Run these commands in Windows PowerShell, using Windows Python 3.9+ and the existing WinGet ffmpeg on PATH. Keep this Windows account logged on.

Install

  1. Open PowerShell in the Windows checkout of this repository.

  2. Run:

    powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\apps\media-worker\scripts\install-windows-worker.ps1
    Get-ScheduledTask -TaskName 'TMBH-TranscodeWorker'
    

    If Python is not found, add -PythonExe 'C:\path\to\python.exe' to the installer command. The optional -JobRoot changes all three queue folders. The task starts immediately, polls every 5 seconds, starts at logon, and is triggered every 5 minutes to recover if it exits. Duplicate starts are ignored; a per-inbox file lock also prevents competing manual workers. The installer can be rerun to update the task.

  3. Verify inbox, done, and failed exist under C:\transcode-jobs. Generate a short input with video and audio:

    ffmpeg -hide_banner -n -f lavfi -i 'testsrc2=size=1280x720:rate=30' -f lavfi -i 'sine=frequency=440:sample_rate=48000' -t 10 -c:v mpeg4 -q:v 3 -c:a aac 'C:\transcode-jobs\sample.mp4'
    if ($LASTEXITCODE -ne 0) { throw 'Sample generation failed' }
    

    Use fresh output/job names when repeating these checks. Existing output files are rejected and preserved. Relative input/output paths resolve against the inbox; absolute Windows paths are recommended. Outputs use their extension to choose the container. Jobs run sequentially.

NVENC H.264 on the RTX 3090

  • Publish a job atomically, so polling never reads a partly written JSON:

    @{ input = 'C:\transcode-jobs\sample.mp4'; output = 'C:\transcode-jobs\nvenc.mp4'; preset = 'nvenc_h264'; crf = 23 } | ConvertTo-Json | Set-Content -Encoding UTF8 'C:\transcode-jobs\inbox\nvenc.tmp'
    Move-Item 'C:\transcode-jobs\inbox\nvenc.tmp' 'C:\transcode-jobs\inbox\nvenc.json'
    
  • Within a poll interval plus encode time, done\nvenc.json and a playable, nonempty C:\transcode-jobs\nvenc.mp4 exist; the inbox job is gone.

  • Inspect the output:

    ffprobe -v error -show_entries stream=codec_name,codec_type -of json 'C:\transcode-jobs\nvenc.mp4'
    

    Expect H.264 video and AAC audio. While encoding, observe NVIDIA's Video Encode graph in Task Manager (use a longer input if needed).

  • Repeat with preset = 'nvenc_hevc', a new job name, and output nvenc-hevc.mp4; expect HEVC video and AAC audio. If the installed ffmpeg lacks hevc_nvenc, expect a failed job with encoder diagnostics instead.

Intel QuickSync H.264

  • Publish a QSV job, omitting crf to exercise the default quality of 23:

    @{ input = 'C:\transcode-jobs\sample.mp4'; output = 'C:\transcode-jobs\qsv.mp4'; preset = 'qsv_h264' } | ConvertTo-Json | Set-Content -Encoding UTF8 'C:\transcode-jobs\inbox\qsv.tmp'
    Move-Item 'C:\transcode-jobs\inbox\qsv.tmp' 'C:\transcode-jobs\inbox\qsv.json'
    
  • Verify done\qsv.json, playable qsv.mp4, and H.264/AAC streams using the ffprobe command above with the QSV output path.

  • Observe the Intel GPU's Video Encode graph during the job. Encoder initialization failures belong in failed and must include ffmpeg's error; the worker never retries with a software video encoder.

Failure and continued polling

  • Queue a missing input:

    @{ input = 'C:\transcode-jobs\does-not-exist.mp4'; output = 'C:\transcode-jobs\must-not-exist.mp4'; preset = 'nvenc_h264' } | ConvertTo-Json | Set-Content -Encoding UTF8 'C:\transcode-jobs\inbox\missing.tmp'
    Move-Item 'C:\transcode-jobs\inbox\missing.tmp' 'C:\transcode-jobs\inbox\missing.json'
    
  • Expect failed\missing.json and failed\missing.json.err, mentioning the missing input. No output is created and the inbox job is gone.

  • Queue a text file as input with a valid preset. Expect a failed JSON and .json.err containing ffmpeg's nonzero exit code and stderr. No final output or .part.mp4 file should remain.

  • Queue malformed JSON, an unknown preset, and a string crf in separate jobs. Each must move to failed with a useful .err file.

  • Queue an existing output path (e.g. the sample). Expect failure without changing the existing file.

  • Queue another valid job with a fresh output name; verify completion after the failed jobs. Reuse a failed job filename and verify both archived jobs and their errors survive (a UUID is added on name collisions).

Task lifecycle and foreground diagnostics

  • Log off and back on; verify the task runs. Stop the task, then verify the repeating trigger starts it again within 5 minutes.

  • For foreground diagnostics or a single pass, stop and disable the task first so its repeating trigger cannot race the manual run:

    Disable-ScheduledTask -TaskName 'TMBH-TranscodeWorker'
    Stop-ScheduledTask -TaskName 'TMBH-TranscodeWorker'
    python .\apps\media-worker\scripts\windows-transcode-worker.py --once
    # Exit status is 1 if any job in this pass failed; otherwise 0.
    Enable-ScheduledTask -TaskName 'TMBH-TranscodeWorker'
    Start-ScheduledTask -TaskName 'TMBH-TranscodeWorker'
    

    Omit --once for continuous foreground polling; press Ctrl+C to stop. A second worker on the same inbox must exit without executing jobs. Force-stopping during an encode can leave a hidden .part output; remove it after confirming no ffmpeg process is using it. Its job stays in the inbox for retry. Normal encode failures clean up the temporary output.