Skip to content

Instantly share code, notes, and snippets.

@infojunkie
Created February 6, 2023 17:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save infojunkie/8f5a9f4cfdc7f339f95e57cc8d54c0d7 to your computer and use it in GitHub Desktop.
Save infojunkie/8f5a9f4cfdc7f339f95e57cc8d54c0d7 to your computer and use it in GitHub Desktop.
Convert ffprobe chapters to cuesheet
#!/usr/bin/env php
<?php
/**
* Convert ffprobe chapters to cuesheet.
*
* This is typically used in a video-to-audio transcoding job:
*
* - ffprobe -show_chapters -print_format json -loglevel -8 video.file > chapters.json
* - ffmpeg -i video.file audio.file
* - chapters2cue audio.file < chapters.json > cuesheet.cue
* - shnsplit -f cuesheet.cue -o "flac flac -s -o %f -" audio.file
* - cuetag cuesheet.cue *.flac
*/
define('FRAME_RATE', 75);
if (empty($argv[1])) {
die("Usage: chapters2cue audio-filename.flac < chapter-filename.json > cue-filename.cue\n");
}
$filename = $argv[1];
$filetype = strtoupper(pathinfo($filename, PATHINFO_EXTENSION));
stream_set_blocking(STDIN, TRUE);
$chapters = json_decode(file_get_contents("php://stdin"), flags: JSON_THROW_ON_ERROR);
print("FILE \"$filename\" $filetype\n");
$start = 0;
foreach ($chapters->chapters as $n => $chapter) {
$track = $n + 1;
print(" TRACK $track AUDIO\n");
$title = $chapter?->tags?->title ?? "Track $track";
print(" TITLE \"$title\"\n");
$timecode = secondsToTimecode((float) $chapter->start_time);
print(" INDEX 01 $timecode\n");
}
function secondsToTimecode($seconds) {
$mm = (int) floor($seconds / 60);
$ss = (int) floor($seconds) % 60;
$ff = (int) round(($seconds - floor($seconds)) * 1000 / FRAME_RATE);
return sprintf("%02d:%02d:%02d", $mm, $ss, $ff);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment