The problem: HLS.js caches quality playlist URLs from the master playlist.
Even when we update the master playlist CID, HLS.js keeps polling the same
static quality CID URL, so it never sees new segments.
The fix:
- Store quality-level CIDs in database (quality_playlists JSONB column)
- Generate master playlist with dynamic URLs (/runs/{id}/quality/{name}/playlist.m3u8)
- Add quality endpoint that fetches LATEST CID from database
- HLS.js now polls our dynamic endpoints which return fresh content
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- resolve_friendly_name_sync: for resolving friendly names in sync code
- get_ipfs_cid_sync: for looking up IPFS CIDs in sync code
These are needed for video streaming callbacks that can't use async/await.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- multi_res_output.py was not tracked, causing import errors
- Update gpu_output.py with recent changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Single player for both live rendering and completed HLS streams
- "From Start" mode plays from beginning (replay/VOD style)
- "Live Edge" mode follows rendering progress
- Uses dynamic playlist endpoint for both modes
- Removes duplicate VOD player code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Returns progress, frame, total_frames from Celery task state
so clients can display rendering progress.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove stream_dir deletion in finally block to prevent IPFS upload failures
- Add on_progress callback to StreamInterpreter for real-time progress updates
- Task now sends progress updates to Celery state during rendering
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add "Run Again" button that reruns the recipe with same parameters
- Add "Delete" button with confirmation to delete run and artifacts
- Consolidate result display into single #action-result span
- Implement POST /runs/rerun/{recipe_id} endpoint
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CUDA sync before encoding to ensure RGB->NV12 kernel completes
- Add debug logging for frame data validation (sum check)
- Handle GPUFrame objects in GPUHLSOutput.write()
- Fix cv2.resize for CuPy arrays (use cupyx.scipy.ndimage.zoom)
- Fix fused pipeline parameter ordering (geometric first, color second)
- Add raindrop-style ripple with random position/freq/decay/amp
- Generate final VOD playlist with #EXT-X-ENDLIST
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Return ipfs_playlist_cid from pending_runs while task is running
- Add Cache-Control: no-cache headers to prevent browser/CDN caching
- Fix streaming clients getting stale playlist CIDs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Recipe should work on both CPU and GPU. The interpreter
auto-selects *_gpu versions when available.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Python fallback path was reading amplitude directly from effect dict
instead of checking dynamic_params first like the CUDA kernel path does.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Zoom now driven by audio energy via core:map-range
- Ripple amplitude reads from dynamic_params in sexp_to_cuda
- Crossfade transition with zoom in/out effect
- Move git clone before COPY in Dockerfile for better caching
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When running with --pool=solo, there may already be a running event loop.
Use thread pool to run async coroutines when a loop is already running.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Downstream code expects arrays with .flags attribute, not GPUFrame.
Extract the underlying gpu/cpu array before returning.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The fallback path was passing raw numpy/cupy arrays to GPU functions
that expect GPUFrame objects with .cpu property.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Audio playback path was being resolved during parsing when database
may not be ready, causing fallback to non-existent path. Now resolves
lazily when stream starts, matching how audio analyzer works.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace slow scipy.ndimage operations with custom CUDA kernels:
- gpu_rotate: AFFINE_WARP_KERNEL (< 1ms vs 20ms for scipy)
- gpu_blend: BLEND_KERNEL for fast alpha blending
- gpu_brightness/contrast: BRIGHTNESS_CONTRAST_KERNEL
- Add gpu_zoom, gpu_hue_shift, gpu_invert, gpu_ripple
Preserve GPU arrays through pipeline:
- Updated _maybe_to_numpy() to keep CuPy arrays for GPU primitives
- Primitives detect CuPy arrays via __cuda_array_interface__
- No unnecessary CPU round-trips between operations
New jit_compiler.py contains all CUDA kernels with FastGPUOps
class using ping-pong buffer strategy for efficient in-place ops.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>