From 7d91340582934e51c4ce831b18e28678f038e210 Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Tue, 19 Oct 2021 17:37:54 +0200 Subject: [PATCH] Reduce audio and video bitrates --- backend/youtube/helpers.go | 17 +++++------------ backend/youtube/youtube.go | 12 +++++++----- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/backend/youtube/helpers.go b/backend/youtube/helpers.go index f206152..810b851 100644 --- a/backend/youtube/helpers.go +++ b/backend/youtube/helpers.go @@ -33,10 +33,9 @@ func FormatDebugString(format *youtubev2.Format, includeURL bool) string { } // SortAudio returns the provided formats ordered in descending preferred -// order. The ideal candidate is 44.1kHz stereo audio in a webm container, with -// the highest available bitrate. +// order. The ideal candidate is opus-encoded stereo audio in a webm container, +// with the lowest available bitrate. func SortAudio(inFormats youtubev2.FormatList) youtubev2.FormatList { - // TODO: sort in-place. var formats youtubev2.FormatList for _, format := range inFormats { if format.FPS == 0 && format.AudioChannels > 0 { @@ -50,12 +49,7 @@ func SortAudio(inFormats youtubev2.FormatList) youtubev2.FormatList { isStereoI := formats[i].AudioChannels == 2 isStereoJ := formats[j].AudioChannels == 2 if isStereoI && isStereoJ { - is48kI := formats[i].AudioSampleRate == "48000" - is48kJ := formats[j].AudioSampleRate == "48000" - if is48kI && is48kJ { - return formats[i].Bitrate > formats[j].Bitrate - } - return is48kI + return formats[i].ContentLength < formats[j].ContentLength } return isStereoI } @@ -69,10 +63,9 @@ func SortAudio(inFormats youtubev2.FormatList) youtubev2.FormatList { // bitrate, with audio channels (needed to allow synced playback on the // website). func SortVideo(inFormats youtubev2.FormatList) youtubev2.FormatList { - // TODO: sort in-place. var formats youtubev2.FormatList for _, format := range inFormats { - if format.FPS > 0 && format.ContentLength > 0 && format.AudioChannels > 0 { + if format.FPS > 0 && format.ContentLength > 0 { formats = append(formats, format) } } @@ -80,7 +73,7 @@ func SortVideo(inFormats youtubev2.FormatList) youtubev2.FormatList { isMP4I := strings.Contains(formats[i].MimeType, "mp4") isMP4J := strings.Contains(formats[j].MimeType, "mp4") if isMP4I && isMP4J { - return formats[i].Bitrate < formats[j].Bitrate + return formats[i].ContentLength < formats[j].ContentLength } return isMP4I }) diff --git a/backend/youtube/youtube.go b/backend/youtube/youtube.go index 204bb7b..d15c886 100644 --- a/backend/youtube/youtube.go +++ b/backend/youtube/youtube.go @@ -88,7 +88,7 @@ func (d *Downloader) Download(ctx context.Context, videoID string) (*media.Media }() go func() { defer close(videoResultChan) - video, videoErr := d.downloadVideo(ctx, video, mediaSet.VideoPath(), mediaSet.ThumbnailPath()) + video, videoErr := d.downloadVideo(ctx, video, mediaSet.VideoPath()) result := videoResult{video, videoErr} videoResultChan <- result wg.Done() @@ -138,6 +138,7 @@ func (d *Downloader) downloadAudio(ctx context.Context, video *youtubev2.Video, if err != nil { return nil, fmt.Errorf("error fetching audio stream: %v", err) } + reader := progressReader{Reader: stream, label: "audio", exp: int(format.ContentLength)} rawAudioFile, err := os.Create(rawOutPath) if err != nil { @@ -148,7 +149,7 @@ func (d *Downloader) downloadAudio(ctx context.Context, video *youtubev2.Video, if err != nil { return nil, fmt.Errorf("error creating encoded audio file: %v", err) } - streamReader := io.TeeReader(stream, encodedAudioFile) + streamReader := io.TeeReader(&reader, encodedAudioFile) var errOut bytes.Buffer cmd := exec.CommandContext(ctx, "ffmpeg", "-i", "-", "-f", rawAudioFormat, "-ar", strconv.Itoa(rawAudioSampleRate), "-acodec", rawAudioCodec, "-") @@ -191,6 +192,7 @@ func (d *Downloader) downloadAudio(ctx context.Context, video *youtubev2.Video, type progressReader struct { io.Reader + label string total, exp int } @@ -198,12 +200,12 @@ func (pw *progressReader) Read(p []byte) (int, error) { n, err := pw.Reader.Read(p) pw.total += n - log.Printf("[ProgressReader] Read %d of %d (%.02f%%) bytes from the provided reader", pw.total, pw.exp, (float32(pw.total)/float32(pw.exp))*100.0) + log.Printf("[ProgressReader] [%s] Read %d of %d (%.02f%%) bytes from the provided reader", pw.label, pw.total, pw.exp, (float32(pw.total)/float32(pw.exp))*100.0) return n, err } -func (d *Downloader) downloadVideo(ctx context.Context, video *youtubev2.Video, outPath string, thumbnailOutPath string) (*media.Video, error) { +func (d *Downloader) downloadVideo(ctx context.Context, video *youtubev2.Video, outPath string) (*media.Video, error) { if len(video.Formats) == 0 { return nil, errors.New("error selecting audio format: no format available") } @@ -219,7 +221,7 @@ func (d *Downloader) downloadVideo(ctx context.Context, video *youtubev2.Video, if err != nil { return nil, fmt.Errorf("error fetching video stream: %v", err) } - reader := progressReader{Reader: stream, exp: int(format.ContentLength)} + reader := progressReader{Reader: stream, label: "video", exp: int(format.ContentLength)} videoFile, err := os.Create(outPath) if err != nil {