Foundation: config, schema/migrations, auth, stable IDs, metadata probing
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
type ffprobeOutput struct {
|
||||
Format ffprobeFormat `json:"format"`
|
||||
Streams []ffprobeStream `json:"streams"`
|
||||
}
|
||||
|
||||
type ffprobeFormat struct {
|
||||
FormatName string `json:"format_name"`
|
||||
Duration string `json:"duration"`
|
||||
BitRate string `json:"bit_rate"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
}
|
||||
|
||||
type ffprobeStream struct {
|
||||
Index int `json:"index"`
|
||||
CodecType string `json:"codec_type"` // "audio", "video", "subtitle", ...
|
||||
CodecName string `json:"codec_name"`
|
||||
SampleRate string `json:"sample_rate"`
|
||||
Channels int `json:"channels"`
|
||||
Duration string `json:"duration"`
|
||||
BitRate string `json:"bit_rate"`
|
||||
Disposition map[string]int `json:"disposition"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
}
|
||||
|
||||
// Prober runs ffprobe to extract tags and technical properties from a
|
||||
// media file.
|
||||
type Prober struct {
|
||||
FFprobePath string
|
||||
}
|
||||
|
||||
// Probe reads metadata from the file at path. path must already be a
|
||||
// validated, absolute filesystem path within a configured music
|
||||
// folder — Probe does not perform any authorization or traversal checks
|
||||
// itself.
|
||||
func (p *Prober) Probe(ctx context.Context, path string) (*Tags, error) {
|
||||
ffprobePath := p.FFprobePath
|
||||
if ffprobePath == "" {
|
||||
ffprobePath = "ffprobe"
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, ffprobePath,
|
||||
"-v", "error",
|
||||
"-print_format", "json",
|
||||
"-show_format",
|
||||
"-show_streams",
|
||||
"--", path,
|
||||
)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
if ee, ok := err.(*exec.ExitError); ok {
|
||||
return nil, fmt.Errorf("ffprobe: %w: %s", err, string(ee.Stderr))
|
||||
}
|
||||
return nil, fmt.Errorf("ffprobe: %w", err)
|
||||
}
|
||||
|
||||
var raw ffprobeOutput
|
||||
if err := json.Unmarshal(out, &raw); err != nil {
|
||||
return nil, fmt.Errorf("parsing ffprobe output: %w", err)
|
||||
}
|
||||
return parseFFprobeOutput(raw), nil
|
||||
}
|
||||
Reference in New Issue
Block a user