provide transcoding support

This commit is contained in:
Kendall Garner 2024-09-01 08:26:30 -07:00
parent da95a644c8
commit 528bef01f0
No known key found for this signature in database
GPG key ID: 18D2767419676C87
24 changed files with 347 additions and 69 deletions

View file

@ -59,6 +59,7 @@ import type {
ShareItemResponse,
MoveItemArgs,
DownloadArgs,
TranscodingArgs,
} from '/@/renderer/api/types';
import { DeletePlaylistResponse, RandomSongListArgs } from './types';
import { ndController } from '/@/renderer/api/navidrome/navidrome-controller';
@ -102,6 +103,7 @@ export type ControllerEndpoint = Partial<{
getSongList: (args: SongListArgs) => Promise<SongListResponse>;
getStructuredLyrics: (args: StructuredLyricsArgs) => Promise<StructuredLyric[]>;
getTopSongs: (args: TopSongListArgs) => Promise<TopSongListResponse>;
getTranscodingUrl: (args: TranscodingArgs) => string;
getUserList: (args: UserListArgs) => Promise<UserListResponse>;
movePlaylistItem: (args: MoveItemArgs) => Promise<void>;
removeFromPlaylist: (args: RemoveFromPlaylistArgs) => Promise<RemoveFromPlaylistResponse>;
@ -152,6 +154,7 @@ const endpoints: ApiController = {
getSongList: jfController.getSongList,
getStructuredLyrics: undefined,
getTopSongs: jfController.getTopSongList,
getTranscodingUrl: jfController.getTranscodingUrl,
getUserList: undefined,
movePlaylistItem: jfController.movePlaylistItem,
removeFromPlaylist: jfController.removeFromPlaylist,
@ -194,6 +197,7 @@ const endpoints: ApiController = {
getSongList: ndController.getSongList,
getStructuredLyrics: ssController.getStructuredLyrics,
getTopSongs: ssController.getTopSongList,
getTranscodingUrl: ssController.getTranscodingUrl,
getUserList: ndController.getUserList,
movePlaylistItem: ndController.movePlaylistItem,
removeFromPlaylist: ndController.removeFromPlaylist,
@ -233,6 +237,7 @@ const endpoints: ApiController = {
getSongList: undefined,
getStructuredLyrics: ssController.getStructuredLyrics,
getTopSongs: ssController.getTopSongList,
getTranscodingUrl: ssController.getTranscodingUrl,
getUserList: undefined,
scrobble: ssController.scrobble,
search: ssController.search3,
@ -568,6 +573,15 @@ const getDownloadUrl = (args: DownloadArgs) => {
)?.(args);
};
const getTranscodingUrl = (args: TranscodingArgs) => {
return (
apiController(
'getTranscodingUrl',
args.apiClientProps.server?.type,
) as ControllerEndpoint['getTranscodingUrl']
)?.(args);
};
export const controller = {
addToPlaylist,
authenticate,
@ -594,6 +608,7 @@ export const controller = {
getSongList,
getStructuredLyrics,
getTopSongList,
getTranscodingUrl,
getUserList,
movePlaylistItem,
removeFromPlaylist,

View file

@ -55,6 +55,7 @@ import {
Song,
MoveItemArgs,
DownloadArgs,
TranscodingArgs,
} from '/@/renderer/api/types';
import { jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api';
import { jfNormalize } from './jellyfin-normalize';
@ -1050,6 +1051,20 @@ const getDownloadUrl = (args: DownloadArgs) => {
return `${apiClientProps.server?.url}/items/${query.id}/download?api_key=${apiClientProps.server?.credential}`;
};
const getTranscodingUrl = (args: TranscodingArgs) => {
const { base, format, bitrate } = args.query;
let url = base.replace('transcodingProtocol=hls', 'transcodingProtocol=http');
if (format) {
url = url.replace('audioCodec=aac', `audioCodec=${format}`);
url = url.replace('transcodingContainer=ts', `transcodingContainer=${format}`);
}
if (bitrate !== undefined) {
url += `&maxStreamingBitrate=${bitrate * 1000}`;
}
return url;
};
export const jfController = {
addToPlaylist,
authenticate,
@ -1075,6 +1090,7 @@ export const jfController = {
getSongDetail,
getSongList,
getTopSongList,
getTranscodingUrl,
movePlaylistItem,
removeFromPlaylist,
scrobble,

View file

@ -34,7 +34,7 @@ const getStreamUrl = (args: {
`&playSessionId=${deviceId}` +
'&container=opus,mp3,aac,m4a,m4b,flac,wav,ogg' +
'&transcodingContainer=ts' +
'&transcodingProtocol=hls'
'&transcodingProtocol=http'
);
};

View file

@ -8,7 +8,7 @@ import { ndType } from './navidrome-types';
import { authenticationFailure, resultWithHeaders } from '/@/renderer/api/utils';
import { useAuthStore } from '/@/renderer/store';
import { ServerListItem } from '/@/renderer/api/types';
import { toast } from '/@/renderer/components';
import { toast } from '/@/renderer/components/toast';
import i18n from '/@/i18n/i18n';
const localSettings = isElectron() ? window.electron.localSettings : null;

View file

@ -28,6 +28,7 @@ import {
SimilarSongsArgs,
Song,
DownloadArgs,
TranscodingArgs,
} from '/@/renderer/api/types';
import { randomString } from '/@/renderer/utils';
import { ServerFeatures } from '/@/renderer/api/features-types';
@ -495,6 +496,19 @@ const getDownloadUrl = (args: DownloadArgs) => {
);
};
const getTranscodingUrl = (args: TranscodingArgs) => {
const { base, format, bitrate } = args.query;
let url = base;
if (format) {
url += `&format=${format}`;
}
if (bitrate !== undefined) {
url += `&maxBitRate=${bitrate}`;
}
return url;
};
export const ssController = {
authenticate,
createFavorite,
@ -506,6 +520,7 @@ export const ssController = {
getSimilarSongs,
getStructuredLyrics,
getTopSongList,
getTranscodingUrl,
removeFavorite,
scrobble,
search3,

View file

@ -1211,3 +1211,13 @@ export type DownloadQuery = {
export type DownloadArgs = {
query: DownloadQuery;
} & BaseEndpointArgs;
export type TranscodingQuery = {
base: string;
bitrate?: number;
format?: string;
};
export type TranscodingArgs = {
query: TranscodingQuery;
} & BaseEndpointArgs;

View file

@ -3,7 +3,7 @@ import isElectron from 'is-electron';
import semverCoerce from 'semver/functions/coerce';
import semverGte from 'semver/functions/gte';
import { z } from 'zod';
import { toast } from '/@/renderer/components';
import { toast } from '/@/renderer/components/toast';
import { useAuthStore } from '/@/renderer/store';
import { ServerListItem } from '/@/renderer/api/types';
import { ServerFeature } from '/@/renderer/api/features-types';