Merge pull request #701 from 3flex/add-streaminfo
Some checks are pending
Lint / Lint TS and CSS (push) Waiting to run
Publish / Build (push) Waiting to run
Publish / Publish (push) Blocked by required conditions
Publish / Deploy (push) Blocked by required conditions
Test / Jest (push) Waiting to run

Add StreamInfo type
This commit is contained in:
Niels van Velzen 2024-11-11 17:56:15 +01:00 committed by GitHub
commit 8b309917c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 50 additions and 29 deletions

View File

@ -232,9 +232,9 @@ export async function getPlaybackInfo(
maxBitrate: number,
deviceProfile: DeviceProfile,
startPosition: number,
mediaSourceId: string,
audioStreamIndex: number,
subtitleStreamIndex: number,
mediaSourceId: string | null,
audioStreamIndex: number | null,
subtitleStreamIndex: number | null,
liveStreamId: string | null = null
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promise<any> {

View File

@ -28,7 +28,7 @@ import { JellyfinApi } from './jellyfinApi';
import { PlaybackManager, PlaybackState } from './playbackManager';
import { CommandHandler } from './commandHandler';
import { getMaxBitrateSupport } from './codecSupportHelper';
import { PlayRequest } from '~/types/global';
import { PlayRequest, StreamInfo } from '~/types/global';
window.castReceiverContext = cast.framework.CastReceiverContext.getInstance();
window.playerManager = window.castReceiverContext.getPlayerManager();
@ -808,7 +808,6 @@ export function setTextTrack(index: number | null): void {
}
}
// TODO no any types
/**
* createMediaInformation
* @param playSessionId - playSessionId
@ -819,8 +818,7 @@ export function setTextTrack(index: number | null): void {
export function createMediaInformation(
playSessionId: string,
item: BaseItemDto,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
streamInfo: any
streamInfo: StreamInfo
): framework.messages.MediaInformation {
const mediaInfo = new cast.framework.messages.MediaInformation();
@ -831,12 +829,12 @@ export function createMediaInformation(
canClientSeek: streamInfo.canClientSeek,
canSeek: streamInfo.canSeek,
itemId: item.Id,
liveStreamId: streamInfo.mediaSource.LiveStreamId,
mediaSourceId: streamInfo.mediaSource.Id,
liveStreamId: streamInfo.mediaSource?.LiveStreamId ?? null,
mediaSourceId: streamInfo.mediaSource?.Id ?? null,
playMethod: streamInfo.isStatic ? 'DirectStream' : 'Transcode',
playSessionId: playSessionId,
runtimeTicks: streamInfo.mediaSource.RunTimeTicks,
startPositionTicks: streamInfo.startPositionTicks || 0,
runtimeTicks: streamInfo.mediaSource?.RunTimeTicks ?? null,
startPositionTicks: streamInfo.startPositionTicks ?? 0,
subtitleStreamIndex: streamInfo.subtitleStreamIndex
};
@ -845,7 +843,7 @@ export function createMediaInformation(
mediaInfo.streamType = cast.framework.messages.StreamType.BUFFERED;
mediaInfo.tracks = streamInfo.tracks;
if (streamInfo.mediaSource.RunTimeTicks) {
if (streamInfo.mediaSource?.RunTimeTicks) {
mediaInfo.duration = Math.floor(
ticksToSeconds(streamInfo.mediaSource.RunTimeTicks)
);

View File

@ -4,6 +4,7 @@ import type {
PlayMethod
} from '@jellyfin/sdk/lib/generated-client';
import { RepeatMode } from '@jellyfin/sdk/lib/generated-client';
import { MediaInformationCustomData } from 'chromecast-caf-receiver/cast.framework.messages';
import { AppStatus } from '../types/appStatus';
import {
broadcastConnectionErrorMessage,
@ -33,7 +34,7 @@ export interface PlaybackState {
mediaType: string | null | undefined;
itemId: string;
audioStreamIndex: null;
audioStreamIndex: number | null;
subtitleStreamIndex: number | null;
mediaSource: MediaSourceInfo | null;
mediaSourceId: string;
@ -199,7 +200,7 @@ export abstract class PlaybackManager {
// Would set private, but some refactorings need to happen first.
static async playItemInternal(
item: BaseItemDto,
options: any // eslint-disable-line @typescript-eslint/no-explicit-any
options: MediaInformationCustomData
): Promise<void> {
DocumentManager.setAppStatus(AppStatus.Loading);

View File

@ -22,7 +22,7 @@ import {
} from '@jellyfin/sdk/lib/utils/api';
import { JellyfinApi } from './components/jellyfinApi';
import { PlaybackManager, PlaybackState } from './components/playbackManager';
import { BusMessage } from './types/global';
import { BusMessage, StreamInfo } from './types/global';
type InstantMixApiRequest =
| InstantMixApiGetInstantMixFromAlbumRequest
@ -309,8 +309,7 @@ export function createStreamInfo(
item: BaseItemDto,
mediaSource: MediaSourceInfo,
startPosition: number | null
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): any {
): StreamInfo {
let mediaUrl;
let contentType;
@ -332,7 +331,7 @@ export function createStreamInfo(
if (type == 'video') {
contentType = `video/${mediaSource.Container}`;
if (mediaSource.SupportsDirectPlay) {
if (mediaSource.SupportsDirectPlay && mediaSource.Path) {
mediaUrl = mediaSource.Path;
isStatic = true;
} else if (mediaSource.SupportsDirectStream) {
@ -363,7 +362,7 @@ export function createStreamInfo(
} else {
contentType = `audio/${mediaSource.Container}`;
if (mediaSource.SupportsDirectPlay) {
if (mediaSource.SupportsDirectPlay && mediaSource.Path) {
mediaUrl = mediaSource.Path;
isStatic = true;
playerStartPositionTicks = startPosition ?? 0;
@ -394,9 +393,8 @@ export function createStreamInfo(
// It is a pain and will require unbinding all event handlers during the operation
const canSeek = (mediaSource.RunTimeTicks ?? 0) > 0;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const info: any = {
audioStreamIndex: mediaSource.DefaultAudioStreamIndex,
const info: StreamInfo = {
audioStreamIndex: mediaSource.DefaultAudioStreamIndex ?? null,
canClientSeek: isStatic || (canSeek && streamContainer == 'm3u8'),
canSeek: canSeek,
contentType: contentType,
@ -405,7 +403,7 @@ export function createStreamInfo(
playerStartPositionTicks: playerStartPositionTicks,
startPositionTicks: startPosition,
streamContainer: streamContainer,
subtitleStreamIndex: mediaSource.DefaultSubtitleStreamIndex,
subtitleStreamIndex: mediaSource.DefaultSubtitleStreamIndex ?? null,
url: mediaUrl
};
@ -431,6 +429,10 @@ export function createStreamInfo(
? subtitleStream.DeliveryUrl
: JellyfinApi.createUrl(subtitleStream.DeliveryUrl);
if (!info.subtitleStreamIndex) {
return;
}
const track = new cast.framework.messages.Track(
info.subtitleStreamIndex,
cast.framework.messages.TrackType.TEXT

32
src/types/global.d.ts vendored
View File

@ -5,9 +5,13 @@ import {
import { SystemVolumeData } from 'chromecast-caf-receiver/cast.framework.system';
import type {
BaseItemDto,
MediaSourceInfo,
RepeatMode
} from '@jellyfin/sdk/lib/generated-client';
import { TextTrackEdgeType } from 'chromecast-caf-receiver/cast.framework.messages';
import type {
TextTrackEdgeType,
Track
} from 'chromecast-caf-receiver/cast.framework.messages';
// Messagebus message
export interface BusMessage {
@ -70,6 +74,22 @@ interface SubtitleAppearance {
textSize: 'smaller' | 'small' | 'large' | 'larger' | 'extralarge';
}
interface StreamInfo {
tracks?: Track[];
audioStreamIndex: number | null;
canClientSeek: boolean;
canSeek: boolean;
contentType: string;
isStatic: boolean;
mediaSource?: MediaSourceInfo;
playerStartPositionTicks?: number;
startPositionTicks: number | null;
streamContainer?: string | null;
subtitleStreamIndex: number | null;
subtitleStreamUrl?: string;
url: string;
}
declare global {
export interface Window {
mediaElement: HTMLElement | null;
@ -86,16 +106,16 @@ declare global {
declare module 'chromecast-caf-receiver/cast.framework.messages' {
interface MediaInformationCustomData {
audioStreamIndex: string;
audioStreamIndex: number | null;
canClientSeek: boolean;
canSeek: boolean;
itemId: string | undefined;
liveStreamId: number;
mediaSourceId: number;
liveStreamId: string | null;
mediaSourceId: string | null;
playMethod: 'DirectStream' | 'Transcode';
playSessionId: string;
runtimeTicks: number;
runtimeTicks: number | null;
startPositionTicks: number;
subtitleStreamIndex: number;
subtitleStreamIndex: number | null;
}
}