mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-15 13:00:25 +02:00
add experimental ytmusic playback for external songs
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useMemo, useRef } from 'react';
|
||||
|
||||
import { api } from '/@/renderer/api';
|
||||
import { youtubeQueries } from '/@/renderer/features/musicbrainz/api/youtube-api';
|
||||
import { TranscodingConfig } from '/@/renderer/store';
|
||||
import { QueueSong } from '/@/shared/types/domain-types';
|
||||
import { QueueSong, ServerType } from '/@/shared/types/domain-types';
|
||||
|
||||
const YOUTUBE_WATCH_BASE = 'https://www.youtube.com/watch?v=';
|
||||
|
||||
export function useSongUrl(
|
||||
song: QueueSong | undefined,
|
||||
@@ -11,10 +15,36 @@ export function useSongUrl(
|
||||
): string | undefined {
|
||||
const prior = useRef(['', '']);
|
||||
|
||||
const isExternal = song?._serverType === ServerType.EXTERNAL;
|
||||
const searchQuery =
|
||||
song && isExternal ? `${song.artistName ?? ''} ${song.name ?? ''}`.trim() : '';
|
||||
|
||||
const youtubeSearch = useQuery({
|
||||
...youtubeQueries.search({ query: searchQuery }),
|
||||
enabled: Boolean(song && isExternal && searchQuery),
|
||||
});
|
||||
|
||||
const externalUrl = useMemo(() => {
|
||||
if (!song || !isExternal) return undefined;
|
||||
if (current && prior.current[0] === song._uniqueId && prior.current[1]) {
|
||||
return prior.current[1];
|
||||
}
|
||||
const url = getYoutubeUrlFromSearchResults(youtubeSearch.data);
|
||||
if (url) prior.current = [song._uniqueId, url];
|
||||
return url;
|
||||
}, [song, isExternal, current, youtubeSearch.data]);
|
||||
|
||||
return useMemo(() => {
|
||||
if (song?._serverId) {
|
||||
// If we are the current track, we do not want a transcoding
|
||||
// reconfiguration to force a restart.
|
||||
if (!song) {
|
||||
prior.current = ['', ''];
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (isExternal) {
|
||||
return externalUrl;
|
||||
}
|
||||
|
||||
if (song._serverId) {
|
||||
if (current && prior.current[0] === song._uniqueId) {
|
||||
return prior.current[1];
|
||||
}
|
||||
@@ -29,18 +59,16 @@ export function useSongUrl(
|
||||
},
|
||||
});
|
||||
|
||||
// transcoding enabled; save the updated result
|
||||
prior.current = [song._uniqueId, url];
|
||||
return url;
|
||||
}
|
||||
|
||||
// no track; clear result
|
||||
prior.current = ['', ''];
|
||||
return undefined;
|
||||
}, [
|
||||
song?._serverId,
|
||||
song?._uniqueId,
|
||||
song?.id,
|
||||
song,
|
||||
isExternal,
|
||||
externalUrl,
|
||||
current,
|
||||
transcode.bitrate,
|
||||
transcode.format,
|
||||
@@ -48,6 +76,16 @@ export function useSongUrl(
|
||||
]);
|
||||
}
|
||||
|
||||
function getYoutubeUrlFromSearchResults(
|
||||
results: Array<{ type: string; videoId?: string }> | undefined,
|
||||
): string | undefined {
|
||||
if (!results?.length) return undefined;
|
||||
const first = results.find((r) => r.type === 'SONG' || r.type === 'VIDEO');
|
||||
return first && 'videoId' in first && first.videoId
|
||||
? `${YOUTUBE_WATCH_BASE}${first.videoId}`
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export const getSongUrl = (song: QueueSong, transcode: TranscodingConfig) => {
|
||||
return api.controller.getStreamUrl({
|
||||
apiClientProps: { serverId: song._serverId },
|
||||
|
||||
Reference in New Issue
Block a user