feat(stream): device-aware remux (HEVC/AV1 + non-aac audio) + TTFF timers
Hueco #3 / 3c (CLI). NewRemuxSource now copies the video for any browser-decodable codec: h264, or HEVC/AV1 when the web says the device decodes them (caps). HEVC is muxed with -tag:v hvc1 (Apple requirement), and non-aac audio (ac3/eac3/dts) is transcoded to aac while the video is still copied (ActionRemuxAudio) — this covers the very common h264+ac3 mkv. Startup instrumentation for time-to-first-frame diagnosis: - remux branch logs [probe=.. spawn=..] - transcodeSource logs 'first fMP4 bytes after ..' (ffmpeg → first output) - serveGrowing logs reads that block >250ms (client seeking ahead of the live edge) + the first read's offset vs produced/estimated size. Verified: caps gate (hls without caps, remux with), hvc1 retag (ffprobe of the /stream output = hevc/hvc1), HEVC playback confirmed on a real iPhone Safari over Tailscale. LAN timeline: probe 16ms, spawn 1ms, first byte 201ms, no serveGrowing blocks.
This commit is contained in:
parent
c18876471c
commit
957d499658
4 changed files with 59 additions and 4 deletions
|
|
@ -27,6 +27,11 @@ type TranscodeOpts struct {
|
|||
SourceHeight int // probed source height — used to derive a sane H.264 level
|
||||
StartSeconds float64
|
||||
FFmpegPath string
|
||||
// VideoTag forces the output stream's codec tag on a copy remux. HEVC muxed
|
||||
// into MP4 must carry the `hvc1` tag (not the default `hev1`) or Safari /
|
||||
// Apple devices refuse to decode it. Empty = leave ffmpeg's default. Only
|
||||
// applied on copy actions (passthrough/remux); a real re-encode sets its own.
|
||||
VideoTag string
|
||||
}
|
||||
|
||||
// Transcoder wraps a long-running ffmpeg child process whose stdout streams
|
||||
|
|
@ -222,8 +227,16 @@ func buildFFmpegArgs(filePath string, opts TranscodeOpts) []string {
|
|||
switch opts.Action {
|
||||
case ActionPassthrough, ActionRemux:
|
||||
args = append(args, "-c:v", "copy", "-c:a", "copy")
|
||||
// HEVC → MP4 needs the hvc1 tag for Apple/Safari (hueco #3 / 3c).
|
||||
if opts.VideoTag != "" {
|
||||
args = append(args, "-tag:v", opts.VideoTag)
|
||||
}
|
||||
case ActionRemuxAudio:
|
||||
args = append(args, "-c:v", "copy", "-c:a", "aac", "-b:a", coalesce(opts.AudioBitrate, "192k"))
|
||||
args = append(args, "-c:v", "copy")
|
||||
if opts.VideoTag != "" {
|
||||
args = append(args, "-tag:v", opts.VideoTag) // HEVC → hvc1 for Apple
|
||||
}
|
||||
args = append(args, "-c:a", "aac", "-b:a", coalesce(opts.AudioBitrate, "192k"))
|
||||
case ActionTranscodeVideo:
|
||||
videoCodec := opts.HWAccel.FFmpegVideoCodec("h264")
|
||||
args = append(args, "-c:v", videoCodec)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue