diff --git a/app/routers/runs.py b/app/routers/runs.py index d462059..6a36abe 100644 --- a/app/routers/runs.py +++ b/app/routers/runs.py @@ -402,25 +402,31 @@ async def get_run( # Detect media type using magic bytes, fall back to database item_type output_cid = run["output_cid"] media_type = None - try: - from ..services.run_service import detect_media_type - cache_path = get_cache_manager().get_by_cid(output_cid) - if cache_path and cache_path.exists(): - simple_type = detect_media_type(cache_path) - media_type = type_to_mime(simple_type) - output_media_type = media_type - except Exception: - pass - # Fall back to database item_type if local detection failed - if not media_type: + + # Streaming runs (with ipfs_cid) are always video/mp4 + if run.get("ipfs_cid"): + media_type = "video/mp4" + output_media_type = media_type + else: try: - import database - item_types = await database.get_item_types(output_cid, run.get("actor_id")) - if item_types: - media_type = type_to_mime(item_types[0].get("type")) + from ..services.run_service import detect_media_type + cache_path = get_cache_manager().get_by_cid(output_cid) + if cache_path and cache_path.exists(): + simple_type = detect_media_type(cache_path) + media_type = type_to_mime(simple_type) output_media_type = media_type except Exception: pass + # Fall back to database item_type if local detection failed + if not media_type: + try: + import database + item_types = await database.get_item_types(output_cid, run.get("actor_id")) + if item_types: + media_type = type_to_mime(item_types[0].get("type")) + output_media_type = media_type + except Exception: + pass artifacts.append({ "cid": output_cid, "step_name": "Output", @@ -568,13 +574,17 @@ async def list_runs( for run in runs: # Add output media info if run.get("output_cid"): - try: - cache_path = cache_manager.get_by_cid(run["output_cid"]) - if cache_path and cache_path.exists(): - simple_type = detect_media_type(cache_path) - run["output_media_type"] = type_to_mime(simple_type) - except Exception: - pass + # Streaming runs (with ipfs_cid) are always video/mp4 + if run.get("ipfs_cid"): + run["output_media_type"] = "video/mp4" + else: + try: + cache_path = cache_manager.get_by_cid(run["output_cid"]) + if cache_path and cache_path.exists(): + simple_type = detect_media_type(cache_path) + run["output_media_type"] = type_to_mime(simple_type) + except Exception: + pass # Add input media info (first 3 inputs) input_previews = [] diff --git a/app/templates/runs/detail.html b/app/templates/runs/detail.html index 3458584..40b0d32 100644 --- a/app/templates/runs/detail.html +++ b/app/templates/runs/detail.html @@ -575,7 +575,7 @@ {# Inline media preview - prefer IPFS URLs when available #}
{% if output_media_type and output_media_type.startswith('image/') %} - + Output @@ -593,14 +593,15 @@
- - {{ run.output_cid }} + + {% if run.ipfs_cid %}{{ run.ipfs_cid }}{% else %}{{ run.output_cid }}{% endif %} {% if run.ipfs_cid %} - IPFS: {{ run.ipfs_cid[:16] }}... + View on IPFS Gateway {% endif %}
diff --git a/tasks/streaming.py b/tasks/streaming.py index 42021b8..5066b5f 100644 --- a/tasks/streaming.py +++ b/tasks/streaming.py @@ -411,6 +411,8 @@ def run_stream( "ffmpeg", "-y", "-i", str(hls_playlist), "-c", "copy", # Just copy streams, no re-encoding + "-movflags", "+faststart", # Move moov atom to start for web playback + "-fflags", "+genpts", # Generate proper timestamps str(final_mp4) ] logger.info(f"Muxing HLS to MP4: {' '.join(mux_cmd)}")