diff --git a/packages/integrations/src/interfaces/media-transcoding/statistics.ts b/packages/integrations/src/interfaces/media-transcoding/statistics.ts index f16d39ae4..916516b77 100644 --- a/packages/integrations/src/interfaces/media-transcoding/statistics.ts +++ b/packages/integrations/src/interfaces/media-transcoding/statistics.ts @@ -4,6 +4,7 @@ export interface TdarrPieSegment { } export interface TdarrStatistics { + libraryName: string; totalFileCount: number; totalTranscodeCount: number; totalHealthCheckCount: number; @@ -11,19 +12,12 @@ export interface TdarrStatistics { failedHealthCheckCount: number; stagedTranscodeCount: number; stagedHealthCheckCount: number; - pies: { - libraryName: string; - libraryId: string; - totalFiles: number; - totalTranscodes: number; - savedSpace: number; - totalHealthChecks: number; - transcodeStatus: TdarrPieSegment[]; - healthCheckStatus: TdarrPieSegment[]; - videoCodecs: TdarrPieSegment[]; - videoContainers: TdarrPieSegment[]; - videoResolutions: TdarrPieSegment[]; - audioCodecs: TdarrPieSegment[]; - audioContainers: TdarrPieSegment[]; - }[]; + totalSavedSpace: number; + transcodeStatus: TdarrPieSegment[]; + healthCheckStatus: TdarrPieSegment[]; + videoCodecs: TdarrPieSegment[]; + videoContainers: TdarrPieSegment[]; + videoResolutions: TdarrPieSegment[]; + audioCodecs: TdarrPieSegment[]; + audioContainers: TdarrPieSegment[]; } diff --git a/packages/integrations/src/media-transcoding/tdarr-integration.ts b/packages/integrations/src/media-transcoding/tdarr-integration.ts index 4c79e0a09..15a47076f 100644 --- a/packages/integrations/src/media-transcoding/tdarr-integration.ts +++ b/packages/integrations/src/media-transcoding/tdarr-integration.ts @@ -20,15 +20,13 @@ export class TdarrIntegration extends Integration { } public async getStatisticsAsync(): Promise { - const url = this.url("/api/v2/cruddb"); + const url = this.url("/api/v2/stats/get-pies"); const response = await fetchWithTrustedCertificatesAsync(url, { method: "POST", - headers: { "content-type": "application/json" }, + headers: { accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ data: { - collection: "StatisticsJSONDB", - mode: "getById", - docID: "statistics", + libraryId: "", // empty string to get all libraries }, }), }); @@ -36,28 +34,29 @@ export class TdarrIntegration extends Integration { const statisticsData = await getStatisticsSchema.parseAsync(await response.json()); return { - totalFileCount: statisticsData.totalFileCount, - totalTranscodeCount: statisticsData.totalTranscodeCount, - totalHealthCheckCount: statisticsData.totalHealthCheckCount, - failedTranscodeCount: statisticsData.table3Count, - failedHealthCheckCount: statisticsData.table6Count, - stagedTranscodeCount: statisticsData.table1Count, - stagedHealthCheckCount: statisticsData.table4Count, - pies: statisticsData.pies.map((pie) => ({ - libraryName: pie[0], - libraryId: pie[1], - totalFiles: pie[2], - totalTranscodes: pie[3], - savedSpace: pie[4] * 1_000_000_000, // file_size is in GB, convert to bytes, - totalHealthChecks: pie[5], - transcodeStatus: pie[6], - healthCheckStatus: pie[7], - videoCodecs: pie[8], - videoContainers: pie[9], - videoResolutions: pie[10], - audioCodecs: pie[11], - audioContainers: pie[12], - })), + libraryName: "All", + totalFileCount: statisticsData.pieStats.totalFiles, + totalTranscodeCount: statisticsData.pieStats.totalTranscodeCount, + totalHealthCheckCount: statisticsData.pieStats.totalHealthCheckCount, + // The Tdarr API only returns a category if there is at least one item in it + failedTranscodeCount: + statisticsData.pieStats.status.transcode.find((transcode) => transcode.name === "Transcode error")?.value ?? 0, + failedHealthCheckCount: + statisticsData.pieStats.status.healthcheck.find((healthcheck) => healthcheck.name === "Error")?.value ?? 0, + stagedTranscodeCount: + statisticsData.pieStats.status.transcode.find((transcode) => transcode.name === "Transcode success")?.value ?? + 0, + stagedHealthCheckCount: + statisticsData.pieStats.status.healthcheck.find((healthcheck) => healthcheck.name === "Queued")?.value ?? 0, + + totalSavedSpace: statisticsData.pieStats.sizeDiff * 1_000_000_000, // sizeDiff is in GB, convert to bytes + transcodeStatus: statisticsData.pieStats.status.transcode, + healthCheckStatus: statisticsData.pieStats.status.healthcheck, + videoCodecs: statisticsData.pieStats.video.codecs, + videoContainers: statisticsData.pieStats.video.containers, + videoResolutions: statisticsData.pieStats.video.resolutions, + audioCodecs: statisticsData.pieStats.audio.codecs, + audioContainers: statisticsData.pieStats.audio.containers, }; } @@ -124,7 +123,7 @@ export class TdarrIntegration extends Integration { healthCheck: item.HealthCheck, transcode: item.TranscodeDecisionMaker, filePath: item.file, - fileSize: item.file_size * 1_000_000, // file_size is in MB, convert to bytes + fileSize: Math.floor(item.file_size * 1_000_000), // file_size is in MB, convert to bytes, floor because it returns as float container: item.container, codec: item.video_codec_name, resolution: item.video_resolution, @@ -162,7 +161,7 @@ export class TdarrIntegration extends Integration { healthCheck: item.HealthCheck, transcode: item.TranscodeDecisionMaker, filePath: item.file, - fileSize: item.file_size * 1_000_000, // file_size is in MB, convert to bytes + fileSize: Math.floor(item.file_size * 1_000_000), // file_size is in MB, convert to bytes, floor because it returns as float container: item.container, codec: item.video_codec_name, resolution: item.video_resolution, diff --git a/packages/integrations/src/media-transcoding/tdarr-validation-schemas.ts b/packages/integrations/src/media-transcoding/tdarr-validation-schemas.ts index a457ca627..43729623a 100644 --- a/packages/integrations/src/media-transcoding/tdarr-validation-schemas.ts +++ b/packages/integrations/src/media-transcoding/tdarr-validation-schemas.ts @@ -1,72 +1,60 @@ import { z } from "zod"; export const getStatisticsSchema = z.object({ - totalFileCount: z.number(), - totalTranscodeCount: z.number(), - totalHealthCheckCount: z.number(), - table3Count: z.number(), - table6Count: z.number(), - table1Count: z.number(), - table4Count: z.number(), - pies: z.array( - z.tuple([ - z.string(), // Library Name - z.string(), // Library ID - z.number(), // File count - z.number(), // Number of transcodes - z.number(), // Space saved (in GB) - z.number(), // Number of health checks - z.array( + pieStats: z.object({ + totalFiles: z.number(), + totalTranscodeCount: z.number(), + sizeDiff: z.number(), + totalHealthCheckCount: z.number(), + status: z.object({ + transcode: z.array( z.object({ - // Transcode Status (Pie segments) name: z.string(), value: z.number(), }), ), - z.array( + healthcheck: z.array( z.object({ - // Health Status (Pie segments) name: z.string(), value: z.number(), }), ), - z.array( + }), + video: z.object({ + codecs: z.array( z.object({ - // Video files - Codecs (Pie segments) name: z.string(), value: z.number(), }), ), - z.array( + containers: z.array( z.object({ - // Video files - Containers (Pie segments) name: z.string(), value: z.number(), }), ), - z.array( + resolutions: z.array( z.object({ - // Video files - Resolutions (Pie segments) name: z.string(), value: z.number(), }), ), - z.array( + }), + audio: z.object({ + codecs: z.array( z.object({ - // Audio files - Codecs (Pie segments) name: z.string(), value: z.number(), }), ), - z.array( + containers: z.array( z.object({ - // Audio files - Containers (Pie segments) name: z.string(), value: z.number(), }), ), - ]), - ), + }), + }), }); export const getNodesResponseSchema = z.record( diff --git a/packages/widgets/src/media-transcoding/panels/statistics.panel.tsx b/packages/widgets/src/media-transcoding/panels/statistics.panel.tsx index 23ab97563..b80dab0dd 100644 --- a/packages/widgets/src/media-transcoding/panels/statistics.panel.tsx +++ b/packages/widgets/src/media-transcoding/panels/statistics.panel.tsx @@ -17,9 +17,10 @@ interface StatisticsPanelProps { export function StatisticsPanel(props: StatisticsPanelProps) { const t = useI18n("widget.mediaTranscoding.panel.statistics"); - const allLibs = props.statistics.pies.find((pie) => pie.libraryName === "All"); + const allLibs = props.statistics; - if (!allLibs) { + // Check if Tdarr hs any Files + if (!(allLibs.totalFileCount > 0)) { return (
{t("empty")} @@ -40,7 +41,7 @@ export function StatisticsPanel(props: StatisticsPanelProps) {