mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-06 20:10:12 +02:00
shamelessly copy transcoding config from NavidromeUI
This commit is contained in:
@@ -8,6 +8,10 @@ import md5 from 'md5';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { contract, ssApiClient } from '/@/renderer/api/subsonic/subsonic-api';
|
import { contract, ssApiClient } from '/@/renderer/api/subsonic/subsonic-api';
|
||||||
|
import {
|
||||||
|
getDefaultTranscodingProfiles,
|
||||||
|
getDirectPlayProfiles,
|
||||||
|
} from '/@/renderer/features/player/components/audio-players';
|
||||||
import { randomString } from '/@/renderer/utils';
|
import { randomString } from '/@/renderer/utils';
|
||||||
import { logFn } from '/@/renderer/utils/logger';
|
import { logFn } from '/@/renderer/utils/logger';
|
||||||
import { getServerUrl } from '/@/renderer/utils/normalize-server-url';
|
import { getServerUrl } from '/@/renderer/utils/normalize-server-url';
|
||||||
@@ -88,44 +92,44 @@ const ALBUM_LIST_SORT_MAPPING: Record<AlbumListSort, AlbumListSortType | undefin
|
|||||||
const MAX_SUBSONIC_ITEMS = 500;
|
const MAX_SUBSONIC_ITEMS = 500;
|
||||||
const SUBSONIC_FAST_BATCH_SIZE = MAX_SUBSONIC_ITEMS * 10;
|
const SUBSONIC_FAST_BATCH_SIZE = MAX_SUBSONIC_ITEMS * 10;
|
||||||
|
|
||||||
const TRANSCODE_DIRECT_PLAY_PROFILES = [
|
// const TRANSCODE_DIRECT_PLAY_PROFILES = [
|
||||||
{
|
// {
|
||||||
audioCodecs: ['mp3'],
|
// audioCodecs: ['mp3'],
|
||||||
containers: ['mp3'],
|
// containers: ['mp3'],
|
||||||
maxAudioChannels: 2,
|
// maxAudioChannels: 2,
|
||||||
protocols: ['http'],
|
// protocols: ['http'],
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
audioCodecs: ['aac'],
|
// audioCodecs: ['aac'],
|
||||||
containers: ['m4a', 'mp4'],
|
// containers: ['m4a', 'mp4'],
|
||||||
maxAudioChannels: 2,
|
// maxAudioChannels: 2,
|
||||||
protocols: ['http'],
|
// protocols: ['http'],
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
audioCodecs: ['vorbis'],
|
// audioCodecs: ['vorbis'],
|
||||||
containers: ['ogg'],
|
// containers: ['ogg'],
|
||||||
maxAudioChannels: 2,
|
// maxAudioChannels: 2,
|
||||||
protocols: ['http'],
|
// protocols: ['http'],
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
audioCodecs: ['opus'],
|
// audioCodecs: ['opus'],
|
||||||
containers: ['ogg', 'webm'],
|
// containers: ['ogg', 'webm'],
|
||||||
maxAudioChannels: 2,
|
// maxAudioChannels: 2,
|
||||||
protocols: ['http'],
|
// protocols: ['http'],
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
audioCodecs: ['pcm'],
|
// audioCodecs: ['pcm'],
|
||||||
containers: ['wav'],
|
// containers: ['wav'],
|
||||||
maxAudioChannels: 2,
|
// maxAudioChannels: 2,
|
||||||
protocols: ['http'],
|
// protocols: ['http'],
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
audioCodecs: ['flac'],
|
// audioCodecs: ['flac'],
|
||||||
containers: ['flac'],
|
// containers: ['flac'],
|
||||||
maxAudioChannels: 2,
|
// maxAudioChannels: 2,
|
||||||
protocols: ['http'],
|
// protocols: ['http'],
|
||||||
},
|
// },
|
||||||
];
|
// ];
|
||||||
|
|
||||||
// const TRANSCODE_UNSUPPORTED_DIRECT_PLAY_PROFILES = [
|
// const TRANSCODE_UNSUPPORTED_DIRECT_PLAY_PROFILES = [
|
||||||
// {
|
// {
|
||||||
@@ -1971,25 +1975,17 @@ export const SubsonicController: InternalControllerEndpoint = {
|
|||||||
if (hasFeature(server, ServerFeature.OS_TRANSCODE_DECISION)) {
|
if (hasFeature(server, ServerFeature.OS_TRANSCODE_DECISION)) {
|
||||||
const maxTranscodingAudioBitrate = 0;
|
const maxTranscodingAudioBitrate = 0;
|
||||||
|
|
||||||
const transcodingProfiles = format?.split(',').map((f) => {
|
const directPlayProfiles = getDirectPlayProfiles();
|
||||||
const trimmedFormat = f.trim();
|
const transcodingProfiles = getDefaultTranscodingProfiles();
|
||||||
|
|
||||||
return {
|
|
||||||
audioCodec: trimmedFormat,
|
|
||||||
container: trimmedFormat,
|
|
||||||
maxAudioChannels: 2,
|
|
||||||
protocol: 'http',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const transcodeDecision = await ssApiClient(apiClientProps).getTranscodeDecision({
|
const transcodeDecision = await ssApiClient(apiClientProps).getTranscodeDecision({
|
||||||
body: {
|
body: {
|
||||||
codecProfiles: [],
|
codecProfiles: [],
|
||||||
directPlayProfiles: TRANSCODE_DIRECT_PLAY_PROFILES,
|
directPlayProfiles,
|
||||||
maxAudioBitrate: 0,
|
maxAudioBitrate: 0,
|
||||||
maxTranscodingAudioBitrate,
|
maxTranscodingAudioBitrate,
|
||||||
name: 'Feishin',
|
name: 'Feishin',
|
||||||
platform: 'Web',
|
platform: navigator.userAgent,
|
||||||
transcodingProfiles,
|
transcodingProfiles,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
|
|||||||
@@ -37,6 +37,52 @@ import { toast } from '/@/shared/components/toast/toast';
|
|||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||||
import { PlayerType } from '/@/shared/types/types';
|
import { PlayerType } from '/@/shared/types/types';
|
||||||
|
|
||||||
|
const CODEC_PROBES = [
|
||||||
|
{ codec: 'mp3', container: 'mp3', mime: 'audio/mpeg' },
|
||||||
|
{ codec: 'aac', container: 'mp4', mime: 'audio/mp4; codecs="mp4a.40.2"' },
|
||||||
|
{ codec: 'opus', container: 'ogg', mime: 'audio/ogg; codecs="opus"' },
|
||||||
|
{ codec: 'vorbis', container: 'ogg', mime: 'audio/ogg; codecs="vorbis"' },
|
||||||
|
{ codec: 'flac', container: 'flac', mime: 'audio/flac' },
|
||||||
|
{ codec: 'wav', container: 'wav', mime: 'audio/wav' },
|
||||||
|
{ codec: 'alac', container: 'mp4', mime: 'audio/mp4; codecs="alac"' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const DEFAULT_TRANSCODING_PROFILES = [
|
||||||
|
{ audioCodec: 'opus', container: 'ogg', protocol: 'http' },
|
||||||
|
{ audioCodec: 'mp3', container: 'mp3', protocol: 'http' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const DIRECT_PLAY_PROFILES: {
|
||||||
|
audioCodecs: string[];
|
||||||
|
containers: string[];
|
||||||
|
protocols: string[];
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
export function getDefaultTranscodingProfiles() {
|
||||||
|
return DEFAULT_TRANSCODING_PROFILES;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDirectPlayProfiles() {
|
||||||
|
return DIRECT_PLAY_PROFILES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shamelessly taken from NavidromeUI
|
||||||
|
function detectBrowserProfile() {
|
||||||
|
const audio = new Audio();
|
||||||
|
|
||||||
|
for (const { codec, container, mime } of CODEC_PROBES) {
|
||||||
|
if (audio.canPlayType(mime) === 'probably') {
|
||||||
|
DIRECT_PLAY_PROFILES.push({
|
||||||
|
audioCodecs: [codec],
|
||||||
|
containers: [container],
|
||||||
|
protocols: ['http'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DIRECT_PLAY_PROFILES;
|
||||||
|
}
|
||||||
|
|
||||||
export const AudioPlayers = () => {
|
export const AudioPlayers = () => {
|
||||||
const playbackType = usePlaybackType();
|
const playbackType = usePlaybackType();
|
||||||
const serverId = useCurrentServerId();
|
const serverId = useCurrentServerId();
|
||||||
@@ -49,6 +95,11 @@ export const AudioPlayers = () => {
|
|||||||
} = usePlaybackSettings();
|
} = usePlaybackSettings();
|
||||||
const { setWebAudio, webAudio: audioContext } = useWebAudio();
|
const { setWebAudio, webAudio: audioContext } = useWebAudio();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('getDirectPlayProfiles');
|
||||||
|
detectBrowserProfile();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SleepTimerHook />
|
<SleepTimerHook />
|
||||||
|
|||||||
Reference in New Issue
Block a user