From 06c456ad1d228e02b0a5d64e57c4e82538bd2c6b Mon Sep 17 00:00:00 2001 From: Christian Benincasa Date: Mon, 20 May 2024 12:32:45 -0400 Subject: [PATCH] Remove ability to disable ffmpeg transcoding; Fixes #440 (#444) --- server/src/api/videoApi.ts | 2 +- .../dao/legacy_migration/legacyDbMigration.ts | 5 +- server/src/ffmpeg/ffmpeg.ts | 26 +- server/src/services/m3uService.ts | 14 +- server/src/stream/plex/plexPlayer.ts | 8 +- server/src/stream/programPlayer.ts | 5 +- types/src/schemas/settingsSchemas.ts | 1 + .../ChannelTranscodingConfig.tsx | 12 +- web/src/pages/settings/FfmpegSettingsPage.tsx | 234 ++++++++---------- web/src/pages/welcome/WelcomePage.tsx | 2 +- 10 files changed, 122 insertions(+), 187 deletions(-) diff --git a/server/src/api/videoApi.ts b/server/src/api/videoApi.ts index 140ad6e69..6ca0ed718 100644 --- a/server/src/api/videoApi.ts +++ b/server/src/api/videoApi.ts @@ -283,7 +283,7 @@ export const videoRouter: RouterPluginAsyncCallback = async (fastify) => { return res .type('application/x-mpegURL') .send( - await req.serverCtx.m3uService.buildChannelM3U( + req.serverCtx.m3uService.buildChannelM3U( req.protocol, req.hostname, req.params.id, diff --git a/server/src/dao/legacy_migration/legacyDbMigration.ts b/server/src/dao/legacy_migration/legacyDbMigration.ts index aa7eeb643..70e7759e4 100644 --- a/server/src/dao/legacy_migration/legacyDbMigration.ts +++ b/server/src/dao/legacy_migration/legacyDbMigration.ts @@ -362,9 +362,8 @@ export class LegacyDbMigrator { numThreads: ffmpegSettings['threads'] as number, concatMuxDelay: ffmpegSettings['concatMuxDelay'] as number, enableLogging: ffmpegSettings['logFfmpeg'] as boolean, - enableTranscoding: ffmpegSettings[ - 'enableFFMPEGTranscoding' - ] as boolean, + // This is ignored now + enableTranscoding: true, audioVolumePercent: ffmpegSettings[ 'audioVolumePercent' ] as number, diff --git a/server/src/ffmpeg/ffmpeg.ts b/server/src/ffmpeg/ffmpeg.ts index afe3abc08..9a8373524 100644 --- a/server/src/ffmpeg/ffmpeg.ts +++ b/server/src/ffmpeg/ffmpeg.ts @@ -16,7 +16,6 @@ import { isNonEmptyString } from '../util/index.js'; const spawn = child_process.spawn; const MAXIMUM_ERROR_DURATION_MS = 60000; -const REALLY_RIDICULOUSLY_HIGH_FPS_FOR_TUNARRS_USECASE = 120; const STILLIMAGE_SUPPORTED_ENCODERS = [ 'mpeg2video', @@ -111,20 +110,6 @@ export class FFMPEG extends (events.EventEmitter as new () => TypedEventEmitter< serverOptions().port }/images/generic-error-screen.png`; this.ffmpegName = 'unnamed ffmpeg'; - if (!this.opts.enableTranscoding) { - // this ensures transcoding is completely disabled even if - // some settings are true - this.opts = { - ...this.opts, - normalizeAudio: false, - normalizeAudioCodec: false, - normalizeVideoCodec: false, - errorScreen: 'kill', - normalizeResolution: false, - audioVolumePercent: 100, - maxFPS: REALLY_RIDICULOUSLY_HIGH_FPS_FOR_TUNARRS_USECASE, - }; - } this.channel = channel; this.ffmpegPath = opts.ffmpegExecutablePath; @@ -339,7 +324,7 @@ export class FFMPEG extends (events.EventEmitter as new () => TypedEventEmitter< } spawnError(title: string, subtitle?: string, duration?: number) { - if (!this.opts.enableTranscoding || this.opts.errorScreen == 'kill') { + if (this.opts.errorScreen === 'kill') { this.logger.error('error: ' + title + ' ; ' + subtitle); this.emit('error', { code: -1, @@ -369,19 +354,12 @@ export class FFMPEG extends (events.EventEmitter as new () => TypedEventEmitter< } spawnOffline(duration: number) { - if (!this.opts.enableTranscoding) { - this.logger.info( - 'The channel has an offline period scheduled for this time slot. FFMPEG transcoding is disabled, so it is not possible to render an offline screen. Ending the stream instead', - ); - this.emit('end', { code: -1, cmd: `offline stream disabled.` }); - return; - } - const streamStats = { videoWidth: this.wantedW, videoHeight: this.wantedH, duration: duration, }; + return this.spawn( { errorTitle: 'offline' }, streamStats, diff --git a/server/src/services/m3uService.ts b/server/src/services/m3uService.ts index 7256ca23c..4b4df0642 100644 --- a/server/src/services/m3uService.ts +++ b/server/src/services/m3uService.ts @@ -1,7 +1,6 @@ import { sortBy } from 'lodash-es'; import { ChannelDB } from '../dao/channelDb.js'; import { FileCacheService } from './fileCacheService.js'; -import { getSettings } from '../dao/settings.js'; /** * Manager and Generate M3U content @@ -80,13 +79,12 @@ export class M3uService { return this.replaceHostOnM3u(host, data); } - async buildChannelM3U( + buildChannelM3U( protocol: string, host: string, channel: string | number, sessionId: number, ) { - const settings = await getSettings(); // Maximum number of streams to concatinate beyond channel starting // If someone passes this number then they probably watch too much television const maxStreamsToPlayInARow = 100; @@ -101,13 +99,9 @@ export class M3uService { // `#EXT-X-STREAM-INF:BANDWIDTH=1123000`, ]; - const ffmpegSettings = settings.ffmpegSettings(); - - if (ffmpegSettings.enableTranscoding) { - lines.push( - `${protocol}://${host}/stream?channel=${channel}&first=0&m3u8=1&session=${sessionId}`, - ); - } + lines.push( + `${protocol}://${host}/stream?channel=${channel}&first=0&m3u8=1&session=${sessionId}`, + ); lines.push( `${protocol}://${host}/stream?channel=${channel}&first=1&m3u8=1&session=${sessionId}`, diff --git a/server/src/stream/plex/plexPlayer.ts b/server/src/stream/plex/plexPlayer.ts index 0b1a4ba73..8aae5a116 100644 --- a/server/src/stream/plex/plexPlayer.ts +++ b/server/src/stream/plex/plexPlayer.ts @@ -12,11 +12,10 @@ import { Writable } from 'stream'; import { isContentBackedLineupIteam } from '../../dao/derived_types/StreamLineup.js'; import { PlexServerSettings } from '../../dao/entities/PlexServerSettings.js'; import { FFMPEG, FfmpegEvents } from '../../ffmpeg/ffmpeg.js'; -import { Player } from '../player.js'; -import { PlexTranscoder } from './plexTranscoder.js'; -import { PlayerContext } from '../player.js'; import { TypedEventEmitter } from '../../types/eventEmitter.js'; import { LoggerFactory } from '../../util/logging/LoggerFactory.js'; +import { Player, PlayerContext } from '../player.js'; +import { PlexTranscoder } from './plexTranscoder.js'; const USED_CLIENTS: Record = {}; export class PlexPlayer extends Player { @@ -99,9 +98,8 @@ export class PlexPlayer extends Player { ) { streamDuration = lineupItem.streamDuration / 1000; } - const deinterlace = ffmpegSettings.enableTranscoding; //for now it will always deinterlace when transcoding is enabled but this is sub-optimal - const stream = await plexTranscoder.getStream(deinterlace); + const stream = await plexTranscoder.getStream(/* deinterlace=*/ true); if (this.killed) { return; } diff --git a/server/src/stream/programPlayer.ts b/server/src/stream/programPlayer.ts index 0fbf11c3c..33e7e0cf3 100644 --- a/server/src/stream/programPlayer.ts +++ b/server/src/stream/programPlayer.ts @@ -158,10 +158,7 @@ export class ProgramPlayer extends Player { channel: StreamContextChannel, type: string, ): Maybe { - if ( - !ffmpegSettings.enableTranscoding || - ffmpegSettings.disableChannelOverlay - ) { + if (ffmpegSettings.disableChannelOverlay) { return; } diff --git a/types/src/schemas/settingsSchemas.ts b/types/src/schemas/settingsSchemas.ts index 66028b006..7e13a0ad7 100644 --- a/types/src/schemas/settingsSchemas.ts +++ b/types/src/schemas/settingsSchemas.ts @@ -14,6 +14,7 @@ export const FfmpegSettingsSchema = z.object({ numThreads: z.number().default(4), concatMuxDelay: z.number().default(0), enableLogging: z.boolean().default(false), + // DEPRECATED enableTranscoding: z.boolean().default(true), audioVolumePercent: z.number().default(100), videoEncoder: z.string().default('mpeg2video'), diff --git a/web/src/components/channel_config/ChannelTranscodingConfig.tsx b/web/src/components/channel_config/ChannelTranscodingConfig.tsx index 16f8042ec..2dbc6a407 100644 --- a/web/src/components/channel_config/ChannelTranscodingConfig.tsx +++ b/web/src/components/channel_config/ChannelTranscodingConfig.tsx @@ -338,9 +338,7 @@ export default function ChannelTranscodingConfig() { name="transcoding.targetResolution" render={() => ( - disabled={ - isNil(ffmpegSettings) || !ffmpegSettings.enableTranscoding - } + disabled={isNil(ffmpegSettings)} label="Channel Resolution" value={targetResString} onChange={(e) => handleResolutionChange(e)} @@ -364,9 +362,7 @@ export default function ChannelTranscodingConfig() { ( ( >({ defaultValues: defaultFfmpegSettings, mode: 'onBlur', }); - const enableTranscoding = watch('enableTranscoding'); - useEffect(() => { if (data) { reset(data); @@ -644,148 +641,125 @@ export default function FfmpegSettingsPage() { Transcoding Options - + + + + Video Options + + {videoFfmpegSettings()} + + + + Audio Options + + {audioFfmpegSettings()} + + + + + Error Options + + + + + Error Screen + ( + + )} + /> + + + If there are issues playing a video, Tunarr will try to use an + error screen as a placeholder while retrying loading the video + every 60 seconds. + + + + + + Error Audio + ( + + )} + /> + + + + + Misc Options + + + ( - + )} /> } - label="Enable FFMPEG Transcoding" + label="Disable Channel Watermark Globally" /> - Transcoding is required for some features like channel overlay and - measures to prevent issues when switching episodes. The trade-off is - quality loss and additional computing resource requirements. + Toggling this option will disable channel watermarks regardless of + channel settings. - {enableTranscoding && ( - <> - - - - Video Options - - {videoFfmpegSettings()} - - - - Audio Options - - {audioFfmpegSettings()} - - - - - Error Options - - - - - Error Screen - ( - - )} - /> - - - If there are issues playing a video, Tunarr will try to use an - error screen as a placeholder while retrying loading the video - every 60 seconds. - - - - - - Error Audio - ( - - )} - /> - - - - - Misc Options - - - ( - - )} - /> - } - label="Disable Channel Watermark Globally" + + ( + + )} /> - - Toggling this option will disable channel watermarks regardless of - channel settings. - - + } + label="Disable Channel Prelude" + /> + + In an attempt to improve playback, Tunarr insets really short clips of + black screen between videos. The idea is that if the stream pauses + because Plex is taking too long to reply, it will pause during one of + those black screens instead of interrupting the last second of a + video. If you suspect these black screens are causing trouble instead + of helping, you can disable them with this option. + + - - ( - - )} - /> - } - label="Disable Channel Prelude" - /> - - In an attempt to improve playback, Tunarr insets really short - clips of black screen between videos. The idea is that if the - stream pauses because Plex is taking too long to reply, it will - pause during one of those black screens instead of interrupting - the last second of a video. If you suspect these black screens are - causing trouble instead of helping, you can disable them with this - option. - - - - )} - FFMPEG is installed. + FFMPEG is installed. Detected version {version?.ffmpeg} ) : ( <>