diff --git a/transcoder/src/api/metadata.go b/transcoder/src/api/metadata.go index 684e81b1..b870d577 100644 --- a/transcoder/src/api/metadata.go +++ b/transcoder/src/api/metadata.go @@ -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) } } diff --git a/transcoder/src/audiostream.go b/transcoder/src/audiostream.go index eae658c4..b1555104 100644 --- a/transcoder/src/audiostream.go +++ b/transcoder/src/audiostream.go @@ -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 { diff --git a/transcoder/src/chapters.go b/transcoder/src/chapters.go index d113a207..dbdd35fb 100644 --- a/transcoder/src/chapters.go +++ b/transcoder/src/chapters.go @@ -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 } diff --git a/transcoder/src/codec.go b/transcoder/src/codec.go index 9c98c110..dac80896 100644 --- a/transcoder/src/codec.go +++ b/transcoder/src/codec.go @@ -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 } } diff --git a/transcoder/src/extract.go b/transcoder/src/extract.go index a4dc358c..40c52532 100644 --- a/transcoder/src/extract.go +++ b/transcoder/src/extract.go @@ -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 } diff --git a/transcoder/src/filestream.go b/transcoder/src/filestream.go index 2efd7830..40ab1824 100644 --- a/transcoder/src/filestream.go +++ b/transcoder/src/filestream.go @@ -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) } diff --git a/transcoder/src/hwaccel.go b/transcoder/src/hwaccel.go index f0fe30eb..c0a24c43 100644 --- a/transcoder/src/hwaccel.go +++ b/transcoder/src/hwaccel.go @@ -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") } diff --git a/transcoder/src/info.go b/transcoder/src/info.go index b3875555..f0b4d2c1 100644 --- a/transcoder/src/info.go +++ b/transcoder/src/info.go @@ -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 diff --git a/transcoder/src/keyframes.go b/transcoder/src/keyframes.go index 1cf47714..5f7213db 100644 --- a/transcoder/src/keyframes.go +++ b/transcoder/src/keyframes.go @@ -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) diff --git a/transcoder/src/metadata.go b/transcoder/src/metadata.go index e9a5cb6e..8116b6db 100644 --- a/transcoder/src/metadata.go +++ b/transcoder/src/metadata.go @@ -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( diff --git a/transcoder/src/stream.go b/transcoder/src/stream.go index cc7dab97..f8743ec0 100644 --- a/transcoder/src/stream.go +++ b/transcoder/src/stream.go @@ -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 } diff --git a/transcoder/src/thumbnails.go b/transcoder/src/thumbnails.go index e15bfbf0..49d18f55 100644 --- a/transcoder/src/thumbnails.go +++ b/transcoder/src/thumbnails.go @@ -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 } diff --git a/transcoder/src/tracker.go b/transcoder/src/tracker.go index a20f75ec..6c68cf10 100644 --- a/transcoder/src/tracker.go +++ b/transcoder/src/tracker.go @@ -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) } } diff --git a/transcoder/src/utils/utils.go b/transcoder/src/utils/utils.go index ad089230..5461d84f 100644 --- a/transcoder/src/utils/utils.go +++ b/transcoder/src/utils/utils.go @@ -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))) } } diff --git a/transcoder/src/videostream.go b/transcoder/src/videostream.go index 8782da83..edb9fc00 100644 --- a/transcoder/src/videostream.go +++ b/transcoder/src/videostream.go @@ -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 {