From 2557402367267109e050a0b2fba2e9e9e812629f Mon Sep 17 00:00:00 2001 From: emeric Date: Sat, 31 May 2025 10:27:53 +0200 Subject: [PATCH] Using track id for the transcoding service --- src/libs/services/auth/CMakeLists.txt | 7 +-- .../services/recommendation/CMakeLists.txt | 6 ++- .../recommendation/IRecommendationService.hpp | 2 + src/libs/services/transcoding/CMakeLists.txt | 5 ++ .../impl/TranscodingResourceHandler.cpp | 28 ++--------- .../impl/TranscodingResourceHandler.hpp | 9 +--- .../transcoding/impl/TranscodingService.cpp | 47 +++++++++++++++++-- .../transcoding/impl/TranscodingService.hpp | 3 +- .../transcoding/ITranscodingService.hpp | 25 ++++++---- .../impl/endpoints/MediaRetrieval.cpp | 7 +-- src/lms/main.cpp | 2 +- .../ui/resource/AudioTranscodingResource.cpp | 18 +------ 12 files changed, 88 insertions(+), 71 deletions(-) diff --git a/src/libs/services/auth/CMakeLists.txt b/src/libs/services/auth/CMakeLists.txt index 3558812d..c664ca98 100644 --- a/src/libs/services/auth/CMakeLists.txt +++ b/src/libs/services/auth/CMakeLists.txt @@ -18,14 +18,11 @@ target_include_directories(lmsauth PRIVATE impl ) -target_link_libraries(lmsauth PRIVATE - lmscore - lmsdatabase - ) - target_link_libraries(lmsauth PUBLIC Boost::system Wt::Wt + lmscore + lmsdatabase ) # PAM diff --git a/src/libs/services/recommendation/CMakeLists.txt b/src/libs/services/recommendation/CMakeLists.txt index b31cf280..cd170732 100644 --- a/src/libs/services/recommendation/CMakeLists.txt +++ b/src/libs/services/recommendation/CMakeLists.txt @@ -21,7 +21,11 @@ target_include_directories(lmsrecommendation PRIVATE ) target_link_libraries(lmsrecommendation PRIVATE - lmsdatabase + lmssom std::filesystem ) + +target_link_libraries(lmsrecommendation PUBLIC + lmsdatabase + ) diff --git a/src/libs/services/recommendation/include/services/recommendation/IRecommendationService.hpp b/src/libs/services/recommendation/include/services/recommendation/IRecommendationService.hpp index 89ef69fc..0872cc69 100644 --- a/src/libs/services/recommendation/include/services/recommendation/IRecommendationService.hpp +++ b/src/libs/services/recommendation/include/services/recommendation/IRecommendationService.hpp @@ -23,6 +23,8 @@ #include #include "core/EnumSet.hpp" +#include "database/ArtistId.hpp" +#include "database/ReleaseId.hpp" #include "database/TrackListId.hpp" #include "database/Types.hpp" #include "services/recommendation/Types.hpp" diff --git a/src/libs/services/transcoding/CMakeLists.txt b/src/libs/services/transcoding/CMakeLists.txt index 2c0f5843..e57e0b5f 100644 --- a/src/libs/services/transcoding/CMakeLists.txt +++ b/src/libs/services/transcoding/CMakeLists.txt @@ -15,3 +15,8 @@ target_include_directories(lmstranscoding PRIVATE target_link_libraries(lmstranscoding PRIVATE lmsav ) + +target_link_libraries(lmstranscoding PUBLIC + lmsdatabase + ) + diff --git a/src/libs/services/transcoding/impl/TranscodingResourceHandler.cpp b/src/libs/services/transcoding/impl/TranscodingResourceHandler.cpp index 0fda5f9e..8c21b93f 100644 --- a/src/libs/services/transcoding/impl/TranscodingResourceHandler.cpp +++ b/src/libs/services/transcoding/impl/TranscodingResourceHandler.cpp @@ -25,39 +25,19 @@ namespace lms::transcoding { - namespace - { - std::size_t doEstimateContentLength(const InputParameters& inputParameters, const OutputParameters& outputParameters) - { - const std::size_t estimatedContentLength{ outputParameters.bitrate / 8 * static_cast(std::chrono::duration_cast(inputParameters.duration).count()) / 1000 }; - return estimatedContentLength; - } - - av::InputParameters toAv(const InputParameters& in) - { - return { .file = in.file, .offset = in.offset, .streamIndex = in.streamIndex }; - } - - av::OutputParameters toAv(const OutputParameters& out) - { - return { .format = static_cast(out.format), .bitrate = out.bitrate, .stripMetadata = out.stripMetadata }; - } - - } // namespace - - std::unique_ptr createResourceHandler(const InputParameters& inputParameters, const OutputParameters& outputParameters, bool estimateContentLength) + std::unique_ptr createResourceHandler(const av::InputParameters& inputParameters, const av::OutputParameters& outputParameters, bool estimateContentLength) { return std::make_unique(inputParameters, outputParameters, estimateContentLength); } // TODO set some nice HTTP return code - TranscodingResourceHandler::TranscodingResourceHandler(const InputParameters& inputParameters, const OutputParameters& outputParameters, bool estimateContentLength) - : _estimatedContentLength{ estimateContentLength ? std::make_optional(doEstimateContentLength(inputParameters, outputParameters)) : std::nullopt } + TranscodingResourceHandler::TranscodingResourceHandler(const av::InputParameters& inputParameters, const av::OutputParameters& outputParameters, std::optional estimatedContentLength) + : _estimatedContentLength{ estimatedContentLength } { try { - _transcoder = av::createTranscoder(toAv(inputParameters), toAv(outputParameters)); + _transcoder = av::createTranscoder(inputParameters, outputParameters); if (_estimatedContentLength) LMS_LOG(TRANSCODING, DEBUG, "Estimated content length = " << *_estimatedContentLength); diff --git a/src/libs/services/transcoding/impl/TranscodingResourceHandler.hpp b/src/libs/services/transcoding/impl/TranscodingResourceHandler.hpp index 26465b1b..89f6d3ce 100644 --- a/src/libs/services/transcoding/impl/TranscodingResourceHandler.hpp +++ b/src/libs/services/transcoding/impl/TranscodingResourceHandler.hpp @@ -23,20 +23,15 @@ #include #include +#include "av/ITranscoder.hpp" #include "core/IResourceHandler.hpp" -#include "services/transcoding/ITranscodingService.hpp" - -namespace lms::av -{ - class ITranscoder; -} namespace lms::transcoding { class TranscodingResourceHandler final : public core::IResourceHandler { public: - TranscodingResourceHandler(const InputParameters& inputParameters, const OutputParameters& outputParameters, bool estimateContentLength); + TranscodingResourceHandler(const av::InputParameters& inputParameters, const av::OutputParameters& outputParameters, std::optional estimatedContentLength); ~TranscodingResourceHandler() override; TranscodingResourceHandler(const TranscodingResourceHandler&) = delete; diff --git a/src/libs/services/transcoding/impl/TranscodingService.cpp b/src/libs/services/transcoding/impl/TranscodingService.cpp index 57a2f57e..1599d3a1 100644 --- a/src/libs/services/transcoding/impl/TranscodingService.cpp +++ b/src/libs/services/transcoding/impl/TranscodingService.cpp @@ -19,19 +19,38 @@ #include "TranscodingService.hpp" +#include "av/ITranscoder.hpp" #include "core/ILogger.hpp" +#include "database/Db.hpp" +#include "database/Session.hpp" +#include "database/Track.hpp" #include "TranscodingResourceHandler.hpp" namespace lms::transcoding { - std::unique_ptr createTranscodingService(core::IChildProcessManager& childProcessManager) + namespace { - return std::make_unique(childProcessManager); + av::OutputParameters toAv(const OutputParameters& out) + { + return { .format = static_cast(out.format), .bitrate = out.bitrate, .stripMetadata = out.stripMetadata }; + } + + std::size_t doEstimateContentLength(std::size_t bitrate, std::chrono::milliseconds duration) + { + const std::size_t estimatedContentLength{ (bitrate / 8 * duration.count()) / 1000 }; + return estimatedContentLength; + } + } // namespace + + std::unique_ptr createTranscodingService(db::Db& db, core::IChildProcessManager& childProcessManager) + { + return std::make_unique(db, childProcessManager); } - TranscodingService::TranscodingService(core::IChildProcessManager& childProcessManager) - : _childProcessManager(childProcessManager) + TranscodingService::TranscodingService(db::Db& db, core::IChildProcessManager& childProcessManager) + : _db{ db } + , _childProcessManager(childProcessManager) { LMS_LOG(TRANSCODING, INFO, "Service started!"); } @@ -43,6 +62,24 @@ namespace lms::transcoding std::unique_ptr TranscodingService::createResourceHandler(const InputParameters& inputParameters, const OutputParameters& outputParameters, bool estimateContentLength) { - return std::make_unique(inputParameters, outputParameters, estimateContentLength); + av::InputParameters avInputParams; + std::optional estimatedContentLength; + { + auto& session{ _db.getTLSSession() }; + auto transaction{ session.createReadTransaction() }; + + db::Track::pointer track{ db::Track::find(session, inputParameters.trackId) }; + if (!track) + return nullptr; + + avInputParams.file = track->getAbsoluteFilePath(); + avInputParams.offset = inputParameters.offset; + avInputParams.streamIndex = inputParameters.streamIndex; + + if (estimateContentLength) + estimatedContentLength = doEstimateContentLength(outputParameters.bitrate, track->getDuration()); + } + + return std::make_unique(avInputParams, toAv(outputParameters), estimatedContentLength); } } // namespace lms::transcoding diff --git a/src/libs/services/transcoding/impl/TranscodingService.hpp b/src/libs/services/transcoding/impl/TranscodingService.hpp index d3c55aee..cfa45eaf 100644 --- a/src/libs/services/transcoding/impl/TranscodingService.hpp +++ b/src/libs/services/transcoding/impl/TranscodingService.hpp @@ -26,7 +26,7 @@ namespace lms::transcoding class TranscodingService : public ITranscodingService { public: - explicit TranscodingService(core::IChildProcessManager& childProcessManager); + explicit TranscodingService(db::Db& db, core::IChildProcessManager& childProcessManager); ~TranscodingService() override; TranscodingService(const TranscodingService&) = delete; @@ -35,6 +35,7 @@ namespace lms::transcoding private: std::unique_ptr createResourceHandler(const InputParameters& inputParameters, const OutputParameters& outputParameters, bool estimateContentLength) override; + db::Db& _db; core::IChildProcessManager& _childProcessManager; }; } // namespace lms::transcoding diff --git a/src/libs/services/transcoding/include/services/transcoding/ITranscodingService.hpp b/src/libs/services/transcoding/include/services/transcoding/ITranscodingService.hpp index 3c383f14..c6fccd01 100644 --- a/src/libs/services/transcoding/include/services/transcoding/ITranscodingService.hpp +++ b/src/libs/services/transcoding/include/services/transcoding/ITranscodingService.hpp @@ -23,19 +23,28 @@ #include #include -namespace lms::core +#include "database/TrackId.hpp" + +namespace lms { - class IChildProcessManager; - class IResourceHandler; -} // namespace lms::core + namespace core + { + class IChildProcessManager; + class IResourceHandler; + } // namespace core + + namespace db + { + class Db; + } +} // namespace lms namespace lms::transcoding { struct InputParameters { - std::filesystem::path file; // Path to the input file - std::chrono::milliseconds duration; // Offset in the input file to start transcoding from - std::chrono::milliseconds offset{}; // Offset in the input file to start transcoding from + db::TrackId trackId; + std::chrono::milliseconds offset{}; // Offset in the track file to start transcoding from std::optional streamIndex; // Index of the stream to be transcoded (select "best" audio stream if not set) }; @@ -63,5 +72,5 @@ namespace lms::transcoding virtual std::unique_ptr createResourceHandler(const InputParameters& inputParameters, const OutputParameters& outputParameters, bool estimateContentLength) = 0; }; - std::unique_ptr createTranscodingService(core::IChildProcessManager& childProcessManager); + std::unique_ptr createTranscodingService(db::Db& db, core::IChildProcessManager& childProcessManager); } // namespace lms::transcoding diff --git a/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp b/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp index d756ea1e..4b5d40c1 100644 --- a/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp +++ b/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp @@ -101,6 +101,7 @@ namespace lms::api::subsonic { transcoding::InputParameters inputParameters; std::optional outputParameters; + std::filesystem::path trackPath; bool estimateContentLength{}; }; @@ -143,10 +144,10 @@ namespace lms::api::subsonic if (!track) throw RequestedDataNotFoundError{}; - parameters.inputParameters.file = track->getAbsoluteFilePath(); - parameters.inputParameters.duration = track->getDuration(); + parameters.inputParameters.trackId = id; parameters.inputParameters.offset = std::chrono::seconds{ timeOffset }; parameters.estimateContentLength = estimateContentLength; + parameters.trackPath = track->getAbsoluteFilePath(); if (format == "raw") // raw => no transcoding return parameters; @@ -309,7 +310,7 @@ namespace lms::api::subsonic if (streamParameters.outputParameters) resourceHandler = core::Service::get()->createResourceHandler(streamParameters.inputParameters, *streamParameters.outputParameters, streamParameters.estimateContentLength); else - resourceHandler = core::createFileResourceHandler(streamParameters.inputParameters.file); + resourceHandler = core::createFileResourceHandler(streamParameters.trackPath); } else { diff --git a/src/lms/main.cpp b/src/lms/main.cpp index fd9a7f12..de5e4364 100644 --- a/src/lms/main.cpp +++ b/src/lms/main.cpp @@ -374,7 +374,7 @@ namespace lms core::Service recommendationService{ recommendation::createRecommendationService(database) }; core::Service playlistGeneratorService{ recommendation::createPlaylistGeneratorService(database, *recommendationService.get()) }; core::Service scannerService{ scanner::createScannerService(database) }; - core::Service transcodingService{ transcoding::createTranscodingService(*childProcessManagerService.get()) }; + core::Service transcodingService{ transcoding::createTranscodingService(database, *childProcessManagerService.get()) }; scannerService->getEvents().scanComplete.connect([&] { // Flush cover cache even if no changes: diff --git a/src/lms/ui/resource/AudioTranscodingResource.cpp b/src/lms/ui/resource/AudioTranscodingResource.cpp index 5cf7f8ee..926985cc 100644 --- a/src/lms/ui/resource/AudioTranscodingResource.cpp +++ b/src/lms/ui/resource/AudioTranscodingResource.cpp @@ -141,22 +141,8 @@ namespace lms::ui // optional parameter std::size_t offset{ readParameterAs(request, "offset").value_or(0) }; - std::filesystem::path trackPath; - { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - - const db::Track::pointer track{ db::Track::find(LmsApp->getDbSession(), *trackId) }; - if (!track) - { - TRANSCODE_LOG(ERROR, "Missing track"); - return std::nullopt; - } - - parameters.inputParameters.file = track->getAbsoluteFilePath(); - parameters.inputParameters.duration = track->getDuration(); - parameters.inputParameters.offset = std::chrono::seconds{ offset }; - } - + parameters.inputParameters.trackId = *trackId; + parameters.inputParameters.offset = std::chrono::seconds{ offset }; parameters.outputParameters.stripMetadata = true; parameters.outputParameters.format = *avFormat; parameters.outputParameters.bitrate = *bitrate;