From 6a3783a4ba1e167b793f79164161eebee7c76a49 Mon Sep 17 00:00:00 2001 From: emeric Date: Sun, 15 Oct 2023 20:49:34 +0200 Subject: [PATCH] Subsonic API: try to not transcode if the requested format/max bitrate is compatible with the actual file --- .../impl/entrypoints/MediaRetrieval.cpp | 51 ++++++++++++------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/libs/subsonic/impl/entrypoints/MediaRetrieval.cpp b/src/libs/subsonic/impl/entrypoints/MediaRetrieval.cpp index dcf50850..cddc758c 100644 --- a/src/libs/subsonic/impl/entrypoints/MediaRetrieval.cpp +++ b/src/libs/subsonic/impl/entrypoints/MediaRetrieval.cpp @@ -19,6 +19,7 @@ #include "MediaRetrieval.hpp" +#include "av/IAudioFile.hpp" #include "av/TranscodeParameters.hpp" #include "av/TranscodeResourceHandlerCreator.hpp" #include "av/Types.hpp" @@ -99,27 +100,41 @@ namespace API::Subsonic parameters.inputFileParameters.duration = track->getDuration(); } - if (format != "raw") // raw => no transcode + if (format == "raw") // raw => no transcode + return parameters; + + const auto audioFile{ Av::parseAudioFile(parameters.inputFileParameters.trackPath) }; + + // check if transcode is really needed or not + // same format as requested, bitrate is lower than requested => no need to transcode + if (const auto streamInfo{ audioFile->getBestStreamInfo() }) { - const User::pointer user{ User::find(context.dbSession, context.userId) }; - if (!user) - throw UserNotAuthorizedError{}; - - Av::TranscodeParameters& transcodeParameters{ parameters.transcodeParameters.emplace() }; - - transcodeParameters.stripMetadata = false; // We want clients to use metadata (offline use, replay gain, etc.) - transcodeParameters.offset = std::chrono::seconds{ timeOffset }; - - if (std::optional requestedFormat{ subsonicStreamFormatToAvFormat(format) }) - transcodeParameters.format = *requestedFormat; - else - transcodeParameters.format = userTranscodeFormatToAvFormat(user->getSubsonicDefaultTranscodeFormat()); - - transcodeParameters.bitrate = user->getSubsonicDefaultTranscodeBitrate(); - if (maxBitRate != 0) - transcodeParameters.bitrate = Utils::clamp(transcodeParameters.bitrate, std::size_t{ 48 }, maxBitRate); + // assume reported codec is "mp3", "opus", "vorbis", etc. + if (StringUtils::stringCaseInsensitiveEqual(streamInfo->codec, format) && (maxBitRate == 0 || (streamInfo->bitrate / 1000) <= maxBitRate)) + { + LMS_LOG(API_SUBSONIC, DEBUG) << "stream parameters are compatible with actual file: no transcode"; + return parameters; + } } + const User::pointer user{ User::find(context.dbSession, context.userId) }; + if (!user) + throw UserNotAuthorizedError{}; + + Av::TranscodeParameters& transcodeParameters{ parameters.transcodeParameters.emplace() }; + + transcodeParameters.stripMetadata = false; // We want clients to use metadata (offline use, replay gain, etc.) + transcodeParameters.offset = std::chrono::seconds{ timeOffset }; + + if (std::optional requestedFormat{ subsonicStreamFormatToAvFormat(format) }) + transcodeParameters.format = *requestedFormat; + else + transcodeParameters.format = userTranscodeFormatToAvFormat(user->getSubsonicDefaultTranscodeFormat()); + + transcodeParameters.bitrate = user->getSubsonicDefaultTranscodeBitrate(); + if (maxBitRate != 0) + transcodeParameters.bitrate = Utils::clamp(transcodeParameters.bitrate, std::size_t{ 48000 }, maxBitRate * 1000); + return parameters; } }