BoxOfColors commited on
Commit
8429f30
·
1 Parent(s): 7a2a7f5

transcode_for_browser: return new path in fresh tmp dir to beat Gradio probe race

Browse files
Files changed (1) hide show
  1. app.py +15 -10
app.py CHANGED
@@ -159,8 +159,10 @@ def strip_audio_from_video(video_path: str, output_path: str) -> None:
159
  def _transcode_for_browser(video_path: str) -> str:
160
  """Re-encode uploaded video to H.264/AAC MP4 so the browser preview widget can play it.
161
 
162
- Overwrites the original file in-place so Gradio serves the H.264 version
163
- and does NOT trigger its own slow fallback conversion.
 
 
164
  Only called on upload — not during generation.
165
  """
166
  if video_path is None:
@@ -173,9 +175,14 @@ def _transcode_for_browser(video_path: str) -> str:
173
  if video_streams and video_streams[0].get("codec_name") == "h264":
174
  print(f"[transcode_for_browser] already H.264, skipping")
175
  return video_path
176
- # Write to a temp file first, then replace original in-place.
177
- # This avoids Gradio's own fallback converter triggering on the H.265 source.
178
- tmp_path = video_path + ".tmp.mp4"
 
 
 
 
 
179
  kwargs = dict(
180
  vcodec="libx264", preset="fast", crf=18,
181
  pix_fmt="yuv420p", movflags="+faststart",
@@ -186,13 +193,11 @@ def _transcode_for_browser(video_path: str) -> str:
186
  else:
187
  kwargs["an"] = None
188
  # map 0:v:0 explicitly to skip non-video streams (e.g. data/timecode tracks)
189
- ffmpeg.input(video_path).output(tmp_path, map="0:v:0", **kwargs).run(
190
  overwrite_output=True, quiet=True
191
  )
192
- import os as _os
193
- _os.replace(tmp_path, video_path)
194
- print(f"[transcode_for_browser] transcoded to H.264 in-place: {video_path}")
195
- return video_path
196
  except Exception as e:
197
  print(f"[transcode_for_browser] failed, using original: {e}")
198
  return video_path
 
159
  def _transcode_for_browser(video_path: str) -> str:
160
  """Re-encode uploaded video to H.264/AAC MP4 so the browser preview widget can play it.
161
 
162
+ Returns a NEW path in a fresh /tmp/gradio/ subdirectory. Gradio probes the
163
+ returned path fresh, sees H.264, and serves it directly without its own
164
+ slow fallback converter. The in-place overwrite approach loses the race
165
+ because Gradio probes the original path at upload time before this callback runs.
166
  Only called on upload — not during generation.
167
  """
168
  if video_path is None:
 
175
  if video_streams and video_streams[0].get("codec_name") == "h264":
176
  print(f"[transcode_for_browser] already H.264, skipping")
177
  return video_path
178
+ # Write to a fresh gradio-served temp dir so Gradio re-probes from scratch
179
+ # and never sees the H.265 source for this returned value.
180
+ import hashlib as _hashlib, os as _os
181
+ basename = _os.path.basename(video_path)
182
+ tag = _hashlib.sha256((video_path + "_h264").encode()).hexdigest()
183
+ out_dir = f"/tmp/gradio/{tag}"
184
+ _os.makedirs(out_dir, exist_ok=True)
185
+ out_path = _os.path.join(out_dir, basename)
186
  kwargs = dict(
187
  vcodec="libx264", preset="fast", crf=18,
188
  pix_fmt="yuv420p", movflags="+faststart",
 
193
  else:
194
  kwargs["an"] = None
195
  # map 0:v:0 explicitly to skip non-video streams (e.g. data/timecode tracks)
196
+ ffmpeg.input(video_path).output(out_path, map="0:v:0", **kwargs).run(
197
  overwrite_output=True, quiet=True
198
  )
199
+ print(f"[transcode_for_browser] transcoded to H.264: {out_path}")
200
+ return out_path
 
 
201
  except Exception as e:
202
  print(f"[transcode_for_browser] failed, using original: {e}")
203
  return video_path