Skip to content

Commit

Permalink
Remove Plex Transcoder. Fixes chrisbenincasa#441 (chrisbenincasa#452)
Browse files Browse the repository at this point in the history
* remove plex transcoder checkpoint

* Forgot to push this file

* Remove usages of plex transcoder on backend. Forces direct play and allows Tunarr to own all normalization logic

* Capitalizing class files

* Remove plex transcode settings from UI
  • Loading branch information
chrisbenincasa authored May 27, 2024
1 parent e15af74 commit b9a0ab7
Show file tree
Hide file tree
Showing 23 changed files with 590 additions and 602 deletions.
2 changes: 1 addition & 1 deletion server/src/api/channelsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import duration from 'dayjs/plugin/duration.js';
import { compact, isError, isNil, map, omit, sortBy } from 'lodash-es';
import z from 'zod';
import { GlobalScheduler } from '../services/scheduler.js';
import { UpdateXmlTvTask } from '../tasks/updateXmlTvTask.js';
import { UpdateXmlTvTask } from '../tasks/UpdateXmlTvTask.js';
import { RouterPluginAsyncCallback } from '../types/serverType.js';
import { attempt, mapAsyncSeq } from '../util/index.js';
import { LoggerFactory } from '../util/logging/LoggerFactory.js';
Expand Down
2 changes: 1 addition & 1 deletion server/src/api/debugApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
isContentBackedLineupIteam,
} from '../dao/derived_types/StreamLineup.js';
import { Channel } from '../dao/entities/Channel.js';
import { PlexPlayer } from '../stream/plex/plexPlayer.js';
import { PlexPlayer } from '../stream/plex/PlexPlayer.js';
import { PlexTranscoder } from '../stream/plex/plexTranscoder.js';
import { FillerPicker } from '../services/FillerPicker.js';
import { StreamContextChannel } from '../stream/types.js';
Expand Down
2 changes: 1 addition & 1 deletion server/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Plex } from '../external/plex.js';
import { FFMPEGInfo } from '../ffmpeg/ffmpegInfo.js';
import { serverOptions } from '../globals.js';
import { GlobalScheduler } from '../services/scheduler.js';
import { UpdateXmlTvTask } from '../tasks/updateXmlTvTask.js';
import { UpdateXmlTvTask } from '../tasks/UpdateXmlTvTask.js';
import { RouterPluginAsyncCallback } from '../types/serverType.js';
import { fileExists } from '../util/fsUtil.js';
import { LoggerFactory } from '../util/logging/LoggerFactory.js';
Expand Down
2 changes: 1 addition & 1 deletion server/src/api/plexServersApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import z from 'zod';
import { PlexServerSettings } from '../dao/entities/PlexServerSettings.js';
import { Plex, PlexApiFactory } from '../external/plex.js';
import { GlobalScheduler } from '../services/scheduler.js';
import { UpdateXmlTvTask } from '../tasks/updateXmlTvTask.js';
import { UpdateXmlTvTask } from '../tasks/UpdateXmlTvTask.js';
import { RouterPluginAsyncCallback } from '../types/serverType.js';
import { firstDefined, wait } from '../util/index.js';
import { LoggerFactory } from '../util/logging/LoggerFactory.js';
Expand Down
2 changes: 1 addition & 1 deletion server/src/api/videoApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ export const videoRouter: RouterPluginAsyncCallback = async (fastify) => {
querystring: StreamQueryStringSchema,
},
onError(req, _, e) {
logger.error('Error on /stream: %s. %O', req.raw.url, e);
logger.error(e, 'Error on /stream: %s. %O', req.raw.url);
},
},
async (req, res) => {
Expand Down
2 changes: 1 addition & 1 deletion server/src/api/xmltvSettingsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { z } from 'zod';
import { defaultXmlTvSettings } from '../dao/settings.js';
import { serverOptions } from '../globals.js';
import { GlobalScheduler } from '../services/scheduler.js';
import { UpdateXmlTvTask } from '../tasks/updateXmlTvTask.js';
import { UpdateXmlTvTask } from '../tasks/UpdateXmlTvTask.js';
import { RouterPluginCallback } from '../types/serverType.js';
import { firstDefined } from '../util/index.js';
import { LoggerFactory } from '../util/logging/LoggerFactory.js';
Expand Down
3 changes: 3 additions & 0 deletions server/src/dao/derived_types/StreamLineup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export type LoadingStreamLineupItem = z.infer<
typeof LoadingStreamLineupItemSchema
>;

const ProgramTypeEnum = z.enum(['movie', 'episode', 'track']);

const BaseContentBackedStreamLineupItemSchema =
baseStreamLineupItemSchema.extend({
programId: z.string().uuid(),
Expand All @@ -67,6 +69,7 @@ const BaseContentBackedStreamLineupItemSchema =
externalSourceId: z.string(),
filePath: z.string(),
externalKey: z.string(),
programType: ProgramTypeEnum,
});

const CommercialStreamLineupItemSchema =
Expand Down
58 changes: 55 additions & 3 deletions server/src/external/plex.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { EntityDTO } from '@mikro-orm/core';
import { DefaultPlexHeaders } from '@tunarr/shared/constants';
import { PlexDvr, PlexDvrsResponse, PlexResource } from '@tunarr/types/plex';
import {
PlexDvr,
PlexDvrsResponse,
PlexMedia,
PlexMediaContainerResponseSchema,
PlexResource,
} from '@tunarr/types/plex';
import axios, {
AxiosInstance,
AxiosRequestConfig,
Expand All @@ -9,7 +15,7 @@ import axios, {
isAxiosError,
} from 'axios';
import { XMLParser } from 'fast-xml-parser';
import { flatMap, forEach, isNil, isUndefined, map } from 'lodash-es';
import { first, flatMap, forEach, isNil, isUndefined, map } from 'lodash-es';
import NodeCache from 'node-cache';
import querystring, { ParsedUrlQueryInput } from 'querystring';
import { MarkOptional } from 'ts-essentials';
Expand All @@ -20,6 +26,7 @@ import {
} from '../types/plexApiTypes.js';
import { Maybe } from '../types/util.js';
import { Logger, LoggerFactory } from '../util/logging/LoggerFactory.js';
import { z } from 'zod';

type AxiosConfigWithMetadata = InternalAxiosRequestConfig & {
metadata: {
Expand Down Expand Up @@ -162,7 +169,7 @@ export class Plex {
};

if (this.accessToken === '') {
throw Error(
throw new Error(
'No Plex token provided. Please use the SignIn method or provide a X-Plex-Token in the Plex constructor.',
);
}
Expand All @@ -171,9 +178,54 @@ export class Plex {
if (!res?.MediaContainer) {
this.logger.error(res, 'Expected MediaContainer, got %O');
}

return res?.MediaContainer;
}

async doTypeCheckedGet<T extends z.ZodTypeAny, Out = z.infer<T>>(
path: string,
schema: T,
optionalHeaders: RawAxiosRequestHeaders = {},
): Promise<Maybe<Out>> {
const req: AxiosRequestConfig = {
method: 'get',
url: path,
headers: optionalHeaders,
};

if (this.accessToken === '') {
throw new Error(
'No Plex token provided. Please use the SignIn method or provide a X-Plex-Token in the Plex constructor.',
);
}

const response = await this.doRequest<unknown>(req);

const parsed = await schema.safeParseAsync(response);

if (parsed.success) {
return parsed.data as Out;
}

this.logger.error(
parsed.error,
'Unable to parse schema from Plex response. Path: %s',
path,
);
return;
}

async getItemMetadata(key: string): Promise<Maybe<PlexMedia>> {
const parsedResponse = await this.doTypeCheckedGet(
`/library/metadata/${key}`,
PlexMediaContainerResponseSchema,
);
if (!isUndefined(parsedResponse)) {
return first(parsedResponse.MediaContainer.Metadata);
}
return;
}

doPut(
path: string,
query: ParsedUrlQueryInput | URLSearchParams = {},
Expand Down
15 changes: 9 additions & 6 deletions server/src/ffmpeg/ffmpeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { isEmpty, isNil, isString, isUndefined, merge, round } from 'lodash-es';
import path from 'path';
import { DeepReadonly, DeepRequired } from 'ts-essentials';
import { serverOptions } from '../globals.js';
import { VideoStats } from '../stream/plex/plexTranscoder.js';
import { StreamDetails } from '../stream/plex/plexTranscoder.js';
import { StreamContextChannel } from '../stream/types.js';
import { Maybe } from '../types/util.js';
import { TypedEventEmitter } from '../types/eventEmitter.js';
Expand Down Expand Up @@ -310,12 +310,10 @@ export class FFMPEG extends (events.EventEmitter as new () => TypedEventEmitter<

spawnStream(
streamUrl: string,
streamStats: Maybe<VideoStats>,
streamStats: Maybe<StreamDetails>,
startTime: Maybe<number>,
duration: Maybe<string>,
enableIcon: Maybe<Watermark>,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_: string, //LineupItem[type]
) {
return this.spawn(
streamUrl,
Expand All @@ -342,7 +340,7 @@ export class FFMPEG extends (events.EventEmitter as new () => TypedEventEmitter<
duration = MAXIMUM_ERROR_DURATION_MS;
}
duration = Math.min(MAXIMUM_ERROR_DURATION_MS, duration);
const streamStats: VideoStats = {
const streamStats: StreamDetails = {
videoWidth: this.wantedW,
videoHeight: this.wantedH,
duration: duration,
Expand Down Expand Up @@ -376,7 +374,7 @@ export class FFMPEG extends (events.EventEmitter as new () => TypedEventEmitter<

spawn(
streamUrl: string | { errorTitle: string; subtitle?: string },
streamStats: Maybe<VideoStats>,
streamStats: Maybe<StreamDetails>,
startTime: Maybe<number>,
duration: Maybe<string>,
limitRead: boolean,
Expand Down Expand Up @@ -566,7 +564,12 @@ export class FFMPEG extends (events.EventEmitter as new () => TypedEventEmitter<
currentAudio = '[audiox]';
}
currentVideo = '[videox]';
} else {
// HACK: We know these will be defined already if we get this far
iW = iW!;
iH = iH!;
}

if (doOverlay && !isNil(watermark?.url)) {
if (watermark.animated) {
ffmpegArgs.push('-ignore_loop', '0');
Expand Down
2 changes: 1 addition & 1 deletion server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { ServerRequestContext, serverContext } from './serverContext.js';
import { GlobalScheduler, scheduleJobs } from './services/scheduler.js';
import { initPersistentStreamCache } from './stream/channelCache.js';
import { runFixers } from './tasks/fixers/index.js';
import { UpdateXmlTvTask } from './tasks/updateXmlTvTask.js';
import { UpdateXmlTvTask } from './tasks/UpdateXmlTvTask.js';
import { filename, isProduction, run } from './util/index.js';
import { LoggerFactory } from './util/logging/LoggerFactory.js';

Expand Down
6 changes: 3 additions & 3 deletions server/src/services/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { OneOffTask } from '../tasks/OneOffTask.js';
import { ReconcileProgramDurationsTask } from '../tasks/ReconcileProgramDurationsTask.js';
import { ScheduledTask } from '../tasks/ScheduledTask.js';
import { Task, TaskId } from '../tasks/Task.js';
import { CleanupSessionsTask } from '../tasks/cleanupSessionsTask.js';
import { ScheduleDynamicChannelsTask } from '../tasks/scheduleDynamicChannelsTask.js';
import { UpdateXmlTvTask } from '../tasks/updateXmlTvTask.js';
import { CleanupSessionsTask } from '../tasks/CleanupSessionsTask.js';
import { ScheduleDynamicChannelsTask } from '../tasks/ScheduleDynamicChannelsTask.js';
import { UpdateXmlTvTask } from '../tasks/UpdateXmlTvTask.js';
import { typedProperty } from '../types/path.js';
import { Maybe } from '../types/util.js';
import { LoggerFactory } from '../util/logging/LoggerFactory.js';
Expand Down
7 changes: 3 additions & 4 deletions server/src/stream/StreamProgramCalculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ export type ProgramAndTimeElapsed = {
};

function programHasRequiredStreamingFields(program: Loaded<ProgramEntity>) {
return every(
[program.plexFilePath, program.plexRatingKey, program.filePath],
negate(isNil),
);
return every([program.plexFilePath, program.filePath], negate(isNil));
}

// any channel thing used here should be added to channel context
Expand Down Expand Up @@ -161,6 +158,7 @@ export class StreamProgramCalculator {
programId: backingItem.uuid,
title: backingItem.title,
id: backingItem.uuid,
programType: backingItem.type,
};
}
} else if (isOfflineItem(lineupItem)) {
Expand Down Expand Up @@ -289,6 +287,7 @@ export class StreamProgramCalculator {
beginningOffset: beginningOffset,
externalSourceId: filler.externalSourceId,
plexFilePath: filler.plexFilePath!,
programType: filler.type,
};
}
// pick the offline screen
Expand Down
Loading

0 comments on commit b9a0ab7

Please sign in to comment.