Compare commits

..

2 Commits

Author SHA1 Message Date
Seungmin Kim
da3957beb3
Merge b493642f21 into 0ec9f3535b 2025-03-25 12:56:31 +00:00
Seungmin Kim
b493642f21 Add ISRC track search for YouTube 2025-03-25 05:56:20 -07:00

View File

@ -241,16 +241,37 @@ class YoutubeSourcedTrack extends SourcedTrack {
required Provider provider, required Provider provider,
required Ref ref, required Ref ref,
}) async { }) async {
final isrcResults = <YoutubeVideoInfo>[]; final matchingResults = <YoutubeVideoInfo>[];
final isrc = track.externalIds?.isrc; final isrc = track.externalIds?.isrc;
if (isrc != null && isrc.isNotEmpty) { if (isrc != null && isrc.isNotEmpty) {
final searchedVideos = await ref.read(provider) final isrcResults = await ref
.read(provider)
.searchVideos(isrc.toString()); .searchVideos(isrc.toString());
isrcResults.addAll(await searchedVideos if (isrcResults.isNotEmpty) {
.map<YoutubeVideoInfo>(YoutubeVideoInfo.fromVideo) for (final videoInfo in isrcResults.map(YoutubeVideoInfo.fromVideo).toList()) {
.toList()); final titleWords =
videoInfo.title
.toLowerCase()
.replaceAll(RegExp(r'[^a-zA-Z0-9\s]+'), '')
.split(RegExp(r'\s+'))
.where((item) => item.isNotEmpty)
.toList();
final nameLower =
track.name!
.toLowerCase()
.replaceAll(RegExp(r'[^a-zA-Z0-9\s]+'), '')
.split(RegExp(r'\s+'))
.where((item) => item.isNotEmpty)
.toList();
final matchCount =
titleWords.where((word) => nameLower.contains(word)).length;
if (matchCount > nameLower.length / 2) {
matchingResults.add(videoInfo);
}
}
}
} }
return isrcResults; return matchingResults;
} }
static Future<List<SiblingType>> fetchSiblings({ static Future<List<SiblingType>> fetchSiblings({
@ -259,19 +280,20 @@ class YoutubeSourcedTrack extends SourcedTrack {
}) async { }) async {
final videoResults = <YoutubeVideoInfo>[]; final videoResults = <YoutubeVideoInfo>[];
videoResults.addAll(await fetchFromIsrc( videoResults.addAll(await fetchFromIsrc(track: track, provider: youtubeEngineProvider, ref: ref));
track: track, provider: youtubeEngineProvider, ref: ref));
final links = await SongLinkService.links(track.id!); final links = await SongLinkService.links(track.id!);
final ytLink = links.firstWhereOrNull((link) => link.platform == "youtube"); final ytLink = links.firstWhereOrNull((link) => link.platform == "youtube");
if (ytLink?.url != null) { if (ytLink?.url != null) {
try { try {
videoResults.add(YoutubeVideoInfo.fromVideo( videoResults.add(
await ref YoutubeVideoInfo.fromVideo(
.read(youtubeEngineProvider) await ref
.getVideo(Uri.parse(ytLink!.url!).queryParameters["v"]!), .read(youtubeEngineProvider)
)); .getVideo(Uri.parse(ytLink!.url!).queryParameters["v"]!),
)
);
} on VideoUnplayableException catch (e, stack) { } on VideoUnplayableException catch (e, stack) {
// Ignore this error and continue with the search // Ignore this error and continue with the search
AppLogger.reportError(e, stack); AppLogger.reportError(e, stack);
@ -280,17 +302,18 @@ class YoutubeSourcedTrack extends SourcedTrack {
final query = SourcedTrack.getSearchTerm(track); final query = SourcedTrack.getSearchTerm(track);
final searchResults = final searchResults = await ref
await ref.read(youtubeEngineProvider).searchVideos(query); .read(youtubeEngineProvider)
.searchVideos(query);
if (ServiceUtils.onlyContainsEnglish(query)) { if (ServiceUtils.onlyContainsEnglish(query)) {
videoResults.addAll( videoResults.addAll(
searchResults.map(YoutubeVideoInfo.fromVideo).toList(), searchResults.map(YoutubeVideoInfo.fromVideo).toList(),
); );
} else { } else {
videoResults.addAll(rankResults( videoResults.addAll(rankResults(
searchResults.map(YoutubeVideoInfo.fromVideo).toList(), searchResults.map(YoutubeVideoInfo.fromVideo).toList(),
track, track,
)); ));
} }