Skip to content

Instantly share code, notes, and snippets.

@Interpause
Last active September 24, 2025 16:31
Show Gist options
  • Select an option

  • Save Interpause/4aa43ebc2b04eecec31bac1994f08f08 to your computer and use it in GitHub Desktop.

Select an option

Save Interpause/4aa43ebc2b04eecec31bac1994f08f08 to your computer and use it in GitHub Desktop.
Snippet to change video speed w/o reencoding video while reencoding audio to maintain pitch
display(Markdown("### Preparing Videos"))
if dataset_df is None:
raise RuntimeError("Dataset DF unavailable.")
all_video_ids = sorted(list(dataset_df['video_id'].dropna().unique()))
logger.info(f"Processing {len(all_video_ids)} unique video IDs.")
skipped = 0
processed = 0
vid_paths = list(extracted_videos_path.glob("*.mp4"))
for vid_path in tqdm(vid_paths, desc="Transforming Videos", unit="video"):
out_path = speed_videos_path / vid_path.name
if out_path.is_file():
skipped += 1
continue
vid_path = str(vid_path.resolve())
out_path = str(out_path.resolve())
# I assume all youtube videos are h264 encoded.
tf_bitstream = tempfile.NamedTemporaryFile(delete=False, suffix=".h264")
tf_audio = tempfile.NamedTemporaryFile(delete=False, suffix=".aac")
tf_final = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
tf_bitstream.close()
tf_audio.close()
tf_final.close()
# Get original FPS.
result = subprocess.run(
["ffprobe", "-v", "error", "-select_streams", "v", "-of", "default=noprint_wrappers=1:nokey=1", "-show_entries", "stream=r_frame_rate", vid_path],
check=True,
capture_output=True,
)
fps = float(fractions.Fraction(result.stdout.decode().strip()))
new_fps = fps * VIDEO_SPEED_FACTOR
# Extract the audio from the mp4 file while also slowing/speeding it up.
factor = VIDEO_SPEED_FACTOR
filter = []
while factor < 0.5:
filter.append("atempo=0.5")
factor /= 0.5
filter.append(f"atempo={factor:.6f}")
filter = ",".join(filter)
subprocess.run(
["ffmpeg", "-y", "-i", vid_path, "-vn", "-filter:a", filter, "-c:a", "aac", tf_audio.name],
check=True,
stderr=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
)
# Extract the h264 bitstream from the mp4 file.
subprocess.run(
["ffmpeg", "-y", "-i", vid_path, "-map", "0:v", "-c:v", "copy", "-bsf:v", "h264_mp4toannexb", tf_bitstream.name],
check=True,
stderr=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
)
# Remux the bitstream with new audio.
subprocess.run(
["ffmpeg", "-y", "-fflags", "+genpts", "-r", f"{new_fps:.6f}", "-i", tf_bitstream.name, "-i", tf_audio.name, "-c:v", "copy", "-c:a", "copy", tf_final.name],
check=True,
stderr=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
)
shutil.move(tf_final.name, out_path)
processed += 1
Path(tf_bitstream.name).unlink(missing_ok=True)
Path(tf_audio.name).unlink(missing_ok=True)
break
print(f"\n\n{skipped} videos skipped, {processed} videos processed, {len(vid_paths)} total.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment