Use sloc for all logs in transcoder

This commit is contained in:
Zoe Roux 2026-04-15 18:31:52 +02:00
parent 2bd3668da4
commit e5e3463c47
No known key found for this signature in database
15 changed files with 71 additions and 79 deletions

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"log/slog"
"mime"
"net/http"
"os"
@ -110,7 +111,7 @@ func (h *mhandler) Prepare(c *echo.Context) error {
info, err := h.metadata.GetMetadata(bgCtx, path, sha)
if err != nil {
fmt.Printf("failed to prepare metadata for %s: %v\n", path, err)
slog.Error("failed to prepare metadata", "path", path, "err", err)
return
}
@ -118,12 +119,12 @@ func (h *mhandler) Prepare(c *echo.Context) error {
for _, video := range info.Videos {
if _, err := h.metadata.GetKeyframes(info, true, video.Index); err != nil {
fmt.Printf("failed to extract video keyframes for %s (stream %d): %v\n", path, video.Index, err)
slog.Warn("failed to extract video keyframes", "path", path, "stream", video.Index, "err", err)
}
}
for _, audio := range info.Audios {
if _, err := h.metadata.GetKeyframes(info, false, audio.Index); err != nil {
fmt.Printf("failed to extract audio keyframes for %s (stream %d): %v\n", path, audio.Index, err)
slog.Warn("failed to extract audio keyframes", "path", path, "stream", audio.Index, "err", err)
}
}

View File

@ -2,7 +2,7 @@ package src
import (
"fmt"
"log"
"log/slog"
)
type AudioStream struct {
@ -12,7 +12,7 @@ type AudioStream struct {
}
func (t *Transcoder) NewAudioStream(file *FileStream, idx uint32, quality AudioQuality) (*AudioStream, error) {
log.Printf("Creating a audio stream %d for %s", idx, file.Info.Path)
slog.Info("creating an audio stream", "idx", idx, "path", file.Info.Path)
keyframes, err := t.metadataService.GetKeyframes(file.Info, false, idx)
if err != nil {

View File

@ -3,6 +3,7 @@ package src
import (
"context"
"fmt"
"log/slog"
"math"
"github.com/zoriya/kyoo/transcoder/src/utils"
@ -23,7 +24,7 @@ func (s *MetadataService) IdentifyChapters(ctx context.Context, info *MediaInfo,
fingerprint, err := s.ComputeFingerprint(ctx, info)
if err != nil {
fmt.Printf("failed to compute fingerprint for %s: %v\n", info.Path, err)
slog.Error("failed to compute fingerprint", "path", info.Path, "err", err)
return
}
@ -32,7 +33,7 @@ func (s *MetadataService) IdentifyChapters(ctx context.Context, info *MediaInfo,
for _, otherPath := range nearEpisodes {
otherCandidates, err := s.compareWithOther(ctx, info, fingerprint, otherPath)
if err != nil {
fmt.Printf("failed to compare %s with %s: %v\n", info.Path, otherPath, err)
slog.Warn("failed to compare episodes", "path", info.Path, "otherPath", otherPath, "err", err)
continue
}
candidates = append(candidates, otherCandidates...)
@ -40,12 +41,12 @@ func (s *MetadataService) IdentifyChapters(ctx context.Context, info *MediaInfo,
chapters := mergeChapters(info, candidates)
if err := s.saveChapters(ctx, info.Id, chapters); err != nil {
fmt.Printf("failed to save chapters for %s: %v\n", info.Path, err)
slog.Error("failed to save chapters", "path", info.Path, "err", err)
return
}
if err := s.DeleteFingerprint(ctx, info.Id); err != nil {
fmt.Printf("failed to delete fingerprint for %s: %v\n", info.Path, err)
slog.Warn("failed to delete fingerprint", "path", info.Path, "err", err)
}
_, err = s.Database.Exec(ctx,
@ -53,7 +54,7 @@ func (s *MetadataService) IdentifyChapters(ctx context.Context, info *MediaInfo,
info.Id, FingerprintVersion,
)
if err != nil {
fmt.Printf("failed to update fingerprint version for %s: %v\n", info.Path, err)
slog.Error("failed to update fingerprint version", "path", info.Path, "err", err)
}
}
@ -105,7 +106,7 @@ func (s *MetadataService) matchByChapterprints(
needle, err := s.GetChapterprint(ctx, *ch.FingerprintId)
if err != nil {
fmt.Printf("failed to get chapterprint %d: %v\n", *ch.FingerprintId, err)
slog.Warn("failed to get chapterprint", "chapterprintId", *ch.FingerprintId, "err", err)
continue
}
@ -118,7 +119,7 @@ func (s *MetadataService) matchByChapterprints(
match, err := FpFindContain(fp, needle)
if err != nil {
fmt.Printf("failed to find chapterprint in fingerprint: %v\n", err)
slog.Warn("failed to find chapterprint in fingerprint", "err", err)
continue
}
if match == nil {
@ -151,7 +152,7 @@ func (s *MetadataService) matchByOverlap(
}
if err := s.StoreFingerprint(ctx, otherInfo.Id, otherPrint); err != nil {
fmt.Printf("failed to store fingerprint for %s: %v\n", otherInfo.Path, err)
slog.Warn("failed to store fingerprint", "path", otherInfo.Path, "err", err)
}
intros, err := FpFindOverlap(fingerprint.Start, otherPrint.Start)
@ -167,13 +168,13 @@ func (s *MetadataService) matchByOverlap(
for _, intro := range intros {
fp, err := ExtractSegment(fingerprint.Start, intro.StartFirst, intro.StartFirst+intro.Duration)
if err != nil {
fmt.Printf("failed to extract segment: %v\n", err)
slog.Warn("failed to extract intro segment", "err", err)
continue
}
fpId, err := s.StoreChapterprint(ctx, fp)
if err != nil {
fmt.Printf("failed to store chapterprint: %v\n", err)
slog.Warn("failed to store intro chapterprint", "err", err)
continue
}
@ -192,13 +193,13 @@ func (s *MetadataService) matchByOverlap(
for _, ov := range credits {
segData, err := ExtractSegment(fingerprint.End, ov.StartFirst, ov.StartFirst+ov.Duration)
if err != nil {
fmt.Printf("failed to extract segment: %v\n", err)
slog.Warn("failed to extract credits segment", "err", err)
continue
}
fpId, err := s.StoreChapterprint(ctx, segData)
if err != nil {
fmt.Printf("failed to store chapterprint: %v\n", err)
slog.Warn("failed to store credits chapterprint", "err", err)
continue
}

View File

@ -2,7 +2,7 @@ package src
import (
"fmt"
"log"
"log/slog"
"strings"
"gopkg.in/vansante/go-ffprobe.v2"
@ -143,7 +143,7 @@ func GetMimeCodec(stream *ffprobe.Stream) *string {
return &ret
default:
log.Printf("No known mime format for: %s", stream.CodecName)
slog.Warn("no known mime format", "codec", stream.CodecName)
return nil
}
}

View File

@ -4,7 +4,7 @@ import (
"context"
"fmt"
"io"
"log"
"log/slog"
"os"
"path/filepath"
"strings"
@ -24,7 +24,7 @@ func (s *MetadataService) ExtractSubs(ctx context.Context, info *MediaInfo) (any
err := s.extractSubs(ctx, info)
if err != nil {
log.Printf("Couldn't extract subs: %v", err)
slog.Error("couldn't extract subs", "err", err)
return set(nil, err)
}
_, err = s.Database.Exec(ctx, `update gocoder.info set ver_extract = $2 where sha = $1`, info.Sha, ExtractVersion)
@ -129,11 +129,11 @@ func (s *MetadataService) extractSubs(ctx context.Context, info *MediaInfo) (err
)
}
}
log.Printf("Starting extraction with the command: %s", cmd)
slog.Info("starting extraction", "command", cmd.String())
cmd.Stdout = nil
if err := cmd.Run(); err != nil {
fmt.Println("Error starting ffmpeg extract:", err)
slog.Error("error starting ffmpeg extract", "err", err)
return err
}
@ -142,7 +142,7 @@ func (s *MetadataService) extractSubs(ctx context.Context, info *MediaInfo) (err
return fmt.Errorf("failed while saving files to backend: %w", err)
}
log.Printf("Extraction finished for %s", info.Path)
slog.Info("extraction finished", "path", info.Path)
return nil
}

View File

@ -3,7 +3,7 @@ package src
import (
"context"
"fmt"
"log"
"log/slog"
"math"
"os"
"slices"
@ -69,7 +69,7 @@ func (fs *FileStream) Kill() {
}
func (fs *FileStream) Destroy() {
log.Printf("Removing all transcode cache files for %s", fs.Info.Path)
slog.Info("removing all transcode cache files", "path", fs.Info.Path)
fs.Kill()
_ = os.RemoveAll(fs.Out)
}

View File

@ -1,7 +1,7 @@
package src
import (
"log"
"log/slog"
"os"
)
@ -10,7 +10,7 @@ func DetectHardwareAccel() HwAccelT {
if name == "disabled" {
name = GetEnvOr("GOTRANSCODER_HWACCEL", "disabled")
}
log.Printf("Using hardware acceleration: %s", name)
slog.Info("using hardware acceleration", "name", name)
// superfast or ultrafast would produce a file extremely big so we prefer to ignore them. Fast is available on all hwaccel modes
// so we use that by default.
@ -107,7 +107,7 @@ func DetectHardwareAccel() HwAccelT {
NoResizeFilter: "format=nv12|cuda,hwupload,scale_cuda=format=nv12",
}
default:
log.Printf("No hardware accelerator named: %s", name)
slog.Error("no hardware accelerator named", "name", name)
os.Exit(2)
panic("unreachable")
}

View File

@ -7,6 +7,7 @@ import (
"encoding/base64"
"encoding/hex"
"fmt"
"log/slog"
"mime"
"os"
"path/filepath"
@ -180,7 +181,7 @@ func ParseFloat(str string) float32 {
func ParseUint(str string) uint32 {
i, err := strconv.ParseUint(str, 10, 32)
if err != nil {
println(str)
slog.Warn("failed to parse uint", "value", str, "err", err)
return 0
}
return uint32(i)
@ -189,7 +190,7 @@ func ParseUint(str string) uint32 {
func ParseInt64(str string) int64 {
i, err := strconv.ParseInt(str, 10, 64)
if err != nil {
println(str)
slog.Warn("failed to parse int64", "value", str, "err", err)
return 0
}
return i

View File

@ -5,7 +5,7 @@ import (
"context"
"errors"
"fmt"
"log"
"log/slog"
"strconv"
"strings"
"sync"
@ -152,7 +152,7 @@ func (s *MetadataService) GetKeyframes(info *MediaInfo, isVideo bool, idx uint32
}
if err != nil {
log.Printf("Couldn't retrieve keyframes for %s %s %d: %v", info.Path, table, idx, err)
slog.Error("couldn't retrieve keyframes", "path", info.Path, "table", table, "idx", idx, "err", err)
return
}
@ -168,7 +168,7 @@ func (s *MetadataService) GetKeyframes(info *MediaInfo, isVideo bool, idx uint32
tx.Exec(ctx, `update gocoder.info set ver_keyframes = $2 where id = $1`, info.Id, KeyframeVersion)
err = tx.Commit(ctx)
if err != nil {
log.Printf("Couldn't store keyframes on database: %v", err)
slog.Error("couldn't store keyframes on database", "err", err)
}
}()
return set(kf, nil)

View File

@ -5,6 +5,7 @@ import (
"encoding/base64"
"errors"
"fmt"
"log/slog"
"os"
"github.com/aws/aws-sdk-go-v2/config"
@ -99,11 +100,11 @@ func (s *MetadataService) setupDb() (*pgxpool.Pool, error) {
db, err := pgxpool.NewWithConfig(ctx, config)
if err != nil {
fmt.Printf("Could not connect to database, check your env variables!\n")
slog.Error("could not connect to database, check your env variables", "err", err)
return nil, err
}
fmt.Println("Migrating database")
slog.Info("migrating database")
dbi := stdlib.OpenDBFromPool(db)
defer dbi.Close()
@ -119,7 +120,7 @@ func (s *MetadataService) setupDb() (*pgxpool.Pool, error) {
return nil, err
}
m.Up()
fmt.Println("Migrating finished")
slog.Info("migrating finished")
return db, nil
}
@ -178,7 +179,7 @@ func (s *MetadataService) GetMetadata(ctx context.Context, path string, sha stri
tx.Exec(bgCtx, `update gocoder.info set ver_keyframes = 0 where id = $1`, ret.Id)
err = tx.Commit(bgCtx)
if err != nil {
fmt.Printf("error deleting old keyframes from database: %v", err)
slog.Error("error deleting old keyframes from database", "err", err)
}
}
@ -191,7 +192,7 @@ func (s *MetadataService) GetMetadata(ctx context.Context, path string, sha stri
tx.Exec(bgCtx, `update gocoder.info set ver_fingerprint = 0 where id = $1`, ret.Id)
err = tx.Commit(bgCtx)
if err != nil {
fmt.Printf("error deleting old fingerprints from database: %v", err)
slog.Error("error deleting old fingerprints from database", "err", err)
}
}
@ -265,7 +266,7 @@ func (s *MetadataService) getMetadata(ctx context.Context, path string, sha stri
}
err = ret.SearchExternalSubtitles()
if err != nil {
fmt.Printf("Couldn't find external subtitles: %v", err)
slog.Warn("couldn't find external subtitles", "err", err)
}
rows, _ = s.Database.Query(

View File

@ -4,7 +4,7 @@ import (
"bufio"
"errors"
"fmt"
"log"
"log/slog"
"math"
"os"
"path/filepath"
@ -155,14 +155,7 @@ func (ts *Stream) run(start int32) error {
ts.heads = append(ts.heads, Head{segment: start, end: end, command: nil})
ts.lock.Unlock()
log.Printf(
"Starting transcode %d for %s (from %d to %d out of %d segments)",
encoder_id,
ts.file.Info.Path,
start,
end,
length,
)
slog.Info("starting transcode", "encoderId", encoder_id, "path", ts.file.Info.Path, "start", start, "end", end, "length", length)
// Include both the start and end delimiter because -ss and -to are not accurate
// Having an extra segment allows us to cut precisely the segments we want with the
@ -279,7 +272,7 @@ func (ts *Stream) run(start int32) error {
)
cmd := exec.Command("ffmpeg", args...)
log.Printf("Running %s", strings.Join(cmd.Args, " "))
slog.Info("running ffmpeg", "args", strings.Join(cmd.Args, " "))
stdout, err := cmd.StdoutPipe()
if err != nil {
@ -312,11 +305,11 @@ func (ts *Stream) run(start int32) error {
}
ts.lock.Lock()
ts.heads[encoder_id].segment = segment
log.Printf("Segment %d got ready (%d)", segment, encoder_id)
slog.Info("segment got ready", "segment", segment, "encoderId", encoder_id)
if ts.isSegmentReady(segment) {
// the current segment is already marked at done so another process has already gone up to here.
cmd.Process.Signal(os.Interrupt)
log.Printf("Killing ffmpeg because segment %d is already ready", segment)
slog.Info("killing ffmpeg because segment already ready", "segment", segment, "encoderId", encoder_id)
should_stop = true
} else {
ts.segments[segment].encoder = encoder_id
@ -326,7 +319,7 @@ func (ts *Stream) run(start int32) error {
should_stop = true
} else if ts.isSegmentReady(segment + 1) {
cmd.Process.Signal(os.Interrupt)
log.Printf("Killing ffmpeg because next segment %d is ready", segment)
slog.Info("killing ffmpeg because next segment is ready", "segment", segment, "encoderId", encoder_id)
should_stop = true
}
}
@ -339,18 +332,18 @@ func (ts *Stream) run(start int32) error {
}
if err := scanner.Err(); err != nil {
log.Println("Error reading stdout of ffmpeg", err)
slog.Warn("error reading ffmpeg stdout", "err", err)
}
}()
go func() {
err := cmd.Wait()
if exiterr, ok := err.(*exec.ExitError); ok && exiterr.ExitCode() == 255 {
log.Printf("ffmpeg %d was killed by us", encoder_id)
slog.Info("ffmpeg was killed by us", "encoderId", encoder_id)
} else if err != nil {
log.Printf("ffmpeg %d occured an error: %s: %s", encoder_id, err, stderr.String())
slog.Error("ffmpeg occured an error", "encoderId", encoder_id, "err", err, "stderr", stderr.String())
} else {
log.Printf("ffmpeg %d finished successfully", encoder_id)
slog.Info("ffmpeg finished successfully", "encoderId", encoder_id)
}
ts.lock.Lock()
@ -410,13 +403,13 @@ func (ts *Stream) GetSegment(segment int32) (string, error) {
if !ready {
// Only start a new encode if there is too big a distance between the current encoder and the segment.
if distance > 60 || !is_scheduled {
log.Printf("Creating new head for %d since closest head is %fs aways", segment, distance)
slog.Info("creating new head", "segment", segment, "distance", distance)
err := ts.run(segment)
if err != nil {
return "", err
}
} else {
log.Printf("Waiting for segment %d since encoder head is %fs aways", segment, distance)
slog.Info("waiting for segment", "segment", segment, "distance", distance)
}
select {
@ -447,7 +440,7 @@ func (ts *Stream) prerareNextSegements(segment int32) {
if ts.getMinEncoderDistance(i) < 60+(5*float64(i-segment)) {
continue
}
log.Printf("Creating new head for future segment (%d)", i)
slog.Info("creating new head for future segment", "segment", i)
go ts.run(i)
return
}

View File

@ -7,7 +7,7 @@ import (
"image"
"image/color"
"io"
"log"
"log/slog"
"math"
"strings"
"sync"
@ -95,7 +95,7 @@ func (s *MetadataService) extractThumbnail(ctx context.Context, path string, sha
gen, err := screengen.NewGenerator(path)
if err != nil {
log.Printf("Error reading video file: %v", err)
slog.Error("error reading video file", "path", path, "err", err)
return err
}
defer gen.Close()
@ -120,13 +120,13 @@ func (s *MetadataService) extractThumbnail(ctx context.Context, path string, sha
sprite := imaging.New(width*columns, height*rows, color.Black)
vtt := "WEBVTT\n\n"
log.Printf("Extracting %d thumbnails for %s (interval of %d).", numcaps, path, interval)
slog.Info("extracting thumbnails", "count", numcaps, "path", path, "interval", interval)
ts := 0
for i := 0; i < numcaps; i++ {
img, err := gen.ImageWxH(int64(ts*1000), width, height)
if err != nil {
log.Printf("Could not generate screenshot %s", err)
slog.Error("could not generate screenshot", "err", err)
return err
}

View File

@ -1,7 +1,7 @@
package src
import (
"log"
"log/slog"
"time"
)
@ -126,7 +126,7 @@ func (t *Tracker) KillStreamIfDead(sha string, path string) bool {
return false
}
}
log.Printf("Nobody is watching %s. Killing it", path)
slog.Info("nobody is watching stream, killing it", "path", path)
stream, ok := t.transcoder.streams.Get(sha)
if !ok {
@ -157,7 +157,7 @@ func (t *Tracker) KillAudioIfDead(sha string, path string, audio AudioKey) bool
return false
}
}
log.Printf("Nobody is listening audio %d of %s. Killing it", audio.idx, path)
slog.Info("nobody is listening audio, killing it", "audioIdx", audio.idx, "path", path)
stream, ok := t.transcoder.streams.Get(sha)
if !ok {
@ -177,7 +177,7 @@ func (t *Tracker) KillVideoIfDead(sha string, path string, video VideoKey) bool
return false
}
}
log.Printf("Nobody is watching %s video %d quality %s. Killing it", path, video.idx, video.quality)
slog.Info("nobody is watching video quality, killing it", "path", path, "videoIdx", video.idx, "quality", video.quality)
stream, ok := t.transcoder.streams.Get(sha)
if !ok {
@ -229,7 +229,7 @@ func (t *Tracker) killOrphanedeheads(stream *Stream, is_video bool) {
distance = min(Abs(ihead-head.segment), distance)
}
if distance > 20 {
log.Printf("Killing orphaned head %s %d", stream.file.Info.Path, encoder_id)
slog.Info("killing orphaned head", "path", stream.file.Info.Path, "encoderId", encoder_id)
stream.KillHead(encoder_id)
}
}

View File

@ -3,17 +3,17 @@ package utils
import (
"errors"
"fmt"
"log"
"log/slog"
"time"
)
func PrintExecTime(message string, args ...any) func() {
msg := fmt.Sprintf(message, args...)
start := time.Now()
log.Printf("Running %s", msg)
slog.Info(fmt.Sprintf("running %s", msg))
return func() {
log.Printf("%s finished in %s", msg, time.Since(start))
slog.Info(fmt.Sprintf("finished %s in %d", msg, time.Since(start)))
}
}

View File

@ -2,7 +2,7 @@ package src
import (
"fmt"
"log"
"log/slog"
)
type VideoStream struct {
@ -12,12 +12,7 @@ type VideoStream struct {
}
func (t *Transcoder) NewVideoStream(file *FileStream, idx uint32, quality VideoQuality) (*VideoStream, error) {
log.Printf(
"Creating a new video stream for %s (n %d) in quality %s",
file.Info.Path,
idx,
quality,
)
slog.Info("creating a new video stream", "path", file.Info.Path, "idx", idx, "quality", quality)
keyframes, err := t.metadataService.GetKeyframes(file.Info, true, idx)
if err != nil {