UNPKG

peertube-plugin-transposer-connector

Version:

Transposer connector is a PeerTube language tool plugin to transcribe and translate with Whisper

299 lines (262 loc) 10.7 kB
const initTransposerController = (router, peertubeHelpers, settingsManager) => { router.post("/transposer/translate/:videoId", async (req, res) => { try { const { videoId } = req.params; peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Received transcription request for video ${videoId}` ); if (!videoId || isNaN(videoId)) { peertubeHelpers.logger.warn( `[transposer-connector] TransposerController: Invalid videoId provided: ${videoId}` ); return res .status(400) .json({ success: false, message: "Invalid videoId provided" }); } // Extract auth header from the request const authHeader = req.headers.authorization; const hasAuth = !!authHeader; peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Processing transcription request for video ${videoId}, auth header present: ${hasAuth}` ); const translationResult = await triggerTransposer( videoId, peertubeHelpers, settingsManager, authHeader ); peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Transcription request completed for video ${videoId}, result: ${translationResult}` ); res.json({ success: translationResult }); } catch (error) { const videoId = req.params.videoId; peertubeHelpers.logger.error( `[transposer-connector] TransposerController: Exception in transcription endpoint for video ${videoId}: ${error.message}` ); res.status(500).send("Internal Server Error"); } }); async function triggerTransposer( videoId, peertubeHelpers, settingsManager, authHeader ) { try { peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Starting transposer trigger process for video ${videoId}` ); var webserverUrl = peertubeHelpers.config.getWebserverUrl(); const settings = await settingsManager.getSettings([ "trigger-transcription-and-translation", ]); if (!webserverUrl) { peertubeHelpers.logger.error( `[transposer-connector] TransposerController: Missing webserver URL configuration` ); return false; } if (!settings["trigger-transcription-and-translation"]) { peertubeHelpers.logger.error( `[transposer-connector] TransposerController: Missing trigger-transcription-and-translation setting in plugin configuration` ); return false; } peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Configuration validated for video ${videoId}, webserverUrl: ${webserverUrl}, triggerUrl: ${settings["trigger-transcription-and-translation"]}` ); // Get video details to extract the language using auth header let video; try { const headers = { Accept: "application/json", }; // Add auth header if available if (authHeader) { headers["Authorization"] = authHeader; peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Using authentication header for video ${videoId} API request` ); } peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Fetching video metadata from PeerTube API for video ${videoId}` ); const response = await fetch( `${webserverUrl}/api/v1/videos/${videoId}`, { headers: headers, } ); if (!response.ok) { peertubeHelpers.logger.error( `[transposer-connector] TransposerController: PeerTube API returned error ${response.status} when fetching video ${videoId} metadata` ); throw new Error(`Failed to fetch video info: ${response.status}`); } video = await response.json(); peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Successfully fetched video metadata for video ${videoId}, name: "${ video.name }", language: ${video.language?.id || "not set"}` ); } catch (error) { peertubeHelpers.logger.error( `[transposer-connector] TransposerController: Exception while fetching video ${videoId} metadata: ${error.message}` ); return false; } const language = video.language?.id; var fileDownloadUrl = video.files?.[0]?.fileDownloadUrl; if (!fileDownloadUrl) { peertubeHelpers.logger.info( `[transposer-connector] TransposerController: No direct fileDownloadUrl found for video ${videoId}, falling back to getVideoFiles() method` ); const videoFiles = await getVideoFiles(videoId, peertubeHelpers); if (videoFiles.length === 0) { peertubeHelpers.logger.warn( `[transposer-connector] TransposerController: No video files found for video ${videoId}, cannot proceed with transcription` ); return false; } peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Found ${videoFiles.length} video files for video ${videoId}, using smallest file (${videoFiles[0].size} bytes)` ); const { url } = videoFiles[0]; peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Using getVideoFiles() method, selected file URL for video ${videoId}` ); fileDownloadUrl = url; } else { peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Using direct fileDownloadUrl from video metadata for video ${videoId}` ); } peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Video ${videoId} file URL obtained, triggering external transcription service` ); const triggerUrl = settings["trigger-transcription-and-translation"]; await triggerTranscriptionAndTranslation( videoId, fileDownloadUrl, language, triggerUrl, webserverUrl, peertubeHelpers ); peertubeHelpers.logger.info( `[transposer-connector] TransposerController: External transcription service triggered successfully for video ${videoId}` ); return true; } catch (error) { peertubeHelpers.logger.error( `[transposer-connector] TransposerController: Failed to trigger transcription and translation for video ${videoId}: ${error.message}` ); return false; } } async function getVideoFiles(id, peertubeHelpers) { peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Fetching video files from PeerTube for video ${id}` ); const videoFilesData = await peertubeHelpers.videos.getFiles(id); if (!videoFilesData) { peertubeHelpers.logger.warn( `[transposer-connector] TransposerController: No video files data returned from PeerTube for video ${id}` ); return []; } const webVideoFiles = videoFilesData.webVideo?.videoFiles || []; const hlsVideoFiles = videoFilesData.hls?.videoFiles || []; peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Video ${id} has ${webVideoFiles.length} web video files and ${hlsVideoFiles.length} HLS video files` ); if (webVideoFiles.length === 0 && hlsVideoFiles.length === 0) { peertubeHelpers.logger.warn( `[transposer-connector] TransposerController: No video files available for video ${id}` ); return []; } const combinedVideoFiles = webVideoFiles.concat(hlsVideoFiles); const sortedVideoFiles = combinedVideoFiles.sort( ({ size: sizeA }, { size: sizeB }) => sizeA - sizeB ); peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Video ${id} files sorted by size, total: ${ sortedVideoFiles.length } files, smallest: ${sortedVideoFiles[0]?.size} bytes, largest: ${ sortedVideoFiles[sortedVideoFiles.length - 1]?.size } bytes` ); return sortedVideoFiles; } function triggerTranscriptionAndTranslation( videoId, downloadUrl, language, triggerUrl, webserverUrl, peertubeHelpers ) { if (!triggerUrl) { peertubeHelpers.logger.error( `[transposer-connector] TransposerController: No trigger URL configured, cannot send transcription request for video ${videoId}` ); return; } peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Sending transcription request to external service for video ${videoId}, triggerUrl: ${triggerUrl}` ); let body = { videoId: videoId, url: downloadUrl, peertubeInstanceBaseDomain: webserverUrl, }; if (language) { body.language = language; peertubeHelpers.logger.info( `[transposer-connector] TransposerController: Including language ${language} in transcription request for video ${videoId}` ); } else { peertubeHelpers.logger.warn( `[transposer-connector] TransposerController: No language specified for video ${videoId} transcription request` ); } fetch(`${triggerUrl}/transcribe-and-translate/video`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify(body), }) .then((response) => { if (!response.ok) { peertubeHelpers.logger.error( `[transposer-connector] TransposerController: External transcription service returned error ${response.status} for video ${videoId}` ); response.json().then((json_error) => { throw new Error( `HTTP error! status: ${response.status} and message ${json_error.message}` ); }); } return response.json(); }) .then((data) => { peertubeHelpers.logger.info( `[transposer-connector] TransposerController: External transcription service responded for video ${videoId}: ${ data.success ? "successful" : "unsuccessful" }` ); }) .catch((error) => { peertubeHelpers.logger.error( `[transposer-connector] TransposerController: Failed to communicate with external transcription service for video ${videoId}: ${error.message}` ); }); } }; module.exports = { initTransposerController, };