stream-poc2/ffmpeg/ffprobe.go
2025-10-09 22:21:38 +02:00

86 lines
1.7 KiB
Go

package ffmpeg
import (
"encoding/hex"
"encoding/json"
"fmt"
"log"
"os"
"os/exec"
"strings"
)
func FFProbe(fname string) (FFProbeOutput, error) {
log.Println("probe", fname)
cmd := exec.Command(
"/usr/bin/ffprobe",
"-loglevel", "error",
fname,
"-show_streams",
"-of", "json",
)
cmd.Stderr = os.Stderr
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Println("Failed to pipe", err)
return FFProbeOutput{}, err
}
err = cmd.Start()
if err != nil {
log.Println("Failed start", err)
return FFProbeOutput{}, err
}
var ffout FFProbeOutput
err = json.NewDecoder(stdout).Decode(&ffout)
if err != nil {
log.Println("Failed to decode", err)
return FFProbeOutput{}, err
}
return ffout, nil
}
func FigureOutHLSCodecsParam(stream FFProbeStream) (string, error) {
// TODO: This is still very lame
var avcProfileBits = map[string]int{
"High": 0x64,
"Main": 0x4D,
"Baseline": 0x42,
}
var hevcProfileBits = map[string]int{
"Main": 1,
"Main 10": 2,
}
if stream.CodecType == "video" {
if stream.CodecName == "h264" {
//avc1.<profile_idc><constraint_set_flags><level_idc>
codecTagBytes, err := hex.DecodeString(strings.TrimPrefix(stream.CodecTag, "0x"))
if err != nil {
return "", err
}
return fmt.Sprintf(
"%s.%02X%02X%02X",
stream.CodecTagString,
avcProfileBits[stream.Profile],
codecTagBytes[1],
stream.Level,
), nil
}
if stream.CodecName == "hevc" {
// hvc1.<profile>.<compatibility>.<tier><level><constraints>
return fmt.Sprintf(
"%s.%d.L%d",
stream.CodecTagString,
hevcProfileBits[stream.Profile],
stream.Level,
), nil
}
}
return "", fmt.Errorf("unrecognized format")
}