add: show metadata, streams, and clock-time ETA in status UI

Surface the fetched job metadata (show/episode or movie title, season,
episode, release/airdate, media type) and the source audio/subtitle streams
through the tracker and /status, and render them in the dashboard's current-job
card. Audio channel counts are now probed and shown as 5.1/2.0/etc.

ETA now reads as a wall-clock finish time plus remaining duration, e.g.
"17:49 (3h52m)". Recent events drop the per-row date for a WhatsApp-style
Today/Yesterday/date divider with time-only rows. All dynamic strings are
HTML-escaped, since metadata and filenames are user-controlled.
This commit is contained in:
Esa Kataja
2026-06-21 18:23:36 +03:00
parent d38c3ad568
commit 35193c695e
4 changed files with 185 additions and 12 deletions
+26
View File
@@ -129,6 +129,7 @@ func processFile(ctx context.Context, inputPath string, cfg *types.Config, enc *
if err != nil {
log.ErrorFile(inputPath, "Getting stream languages", err.Error())
}
tracker.SetStreams(toStatusStreams(streamLangs))
mediaType := metadata.ParseMediaType(filename)
if mediaType == "" {
@@ -176,6 +177,16 @@ func processFile(ctx context.Context, inputPath string, cfg *types.Config, enc *
}
meta.OriginalMedia = mediaType
tracker.SetMeta(status.JobMeta{
IsSeries: meta.IsSeries,
Title: meta.Title,
Collection: meta.Collection,
Season: meta.Season,
Episode: meta.Episode,
DateReleased: meta.DateReleased,
MediaType: string(mediaType),
})
job := &types.Job{
InputPath: inputPath,
MediaType: mediaType,
@@ -241,6 +252,21 @@ func failToFailed(path, failedDir string, log *logger.Logger) {
}
}
// toStatusStreams maps probed source streams to the display shape, keeping only
// audio and subtitle streams (the video stream isn't shown).
func toStatusStreams(streams []encoder.StreamMetadata) []status.Stream {
var out []status.Stream
for _, s := range streams {
switch s.CodecType {
case "audio":
out = append(out, status.Stream{Kind: "audio", Language: s.Language, Codec: s.CodecName, Channels: s.Channels, Title: s.Title})
case "subtitle":
out = append(out, status.Stream{Kind: "subtitle", Language: s.Language, Codec: s.CodecName, Title: s.Title})
}
}
return out
}
func generateRandomString(length int) string {
bytes := make([]byte, length/2+1)
rand.Read(bytes)