Skip to content

Commit 7bbd9ea

Browse files
committed
feat: detect soundtrack based on the release title
1 parent 26c384a commit 7bbd9ea

File tree

2 files changed

+90
-8
lines changed

2 files changed

+90
-8
lines changed

harmonizer/release_types.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,51 @@ describe('release types', () => {
4242
['should detect type before comment', 'Enter Suicidal Angels - EP (Remastered 2021)', new Set(['EP'])],
4343
['should detect EP suffix', 'Zero Distance EP', new Set(['EP'])],
4444
['should detect demo type', 'Parasite Inc. (Demo)', new Set(['Demo'])],
45+
// Soundtrack releases
46+
...([
47+
// Titles with original/official <medium> soundtrack
48+
'The Lord of the Rings: The Return of the King (Original Motion Picture Soundtrack)',
49+
'The Bodyguard - Original Soundtrack Album',
50+
'Plants Vs. Zombies (Original Video Game Soundtrack)',
51+
'Stardew Valley (Original Game Soundtrack)',
52+
'L.A. Noire Official Soundtrack',
53+
'Tarzan (Deutscher Original Film-Soundtrack)',
54+
'Die Eiskönigin Völlig Unverfroren (Deutscher Original Film Soundtrack)',
55+
// Soundtrack from the ... <medium>
56+
'KPop Demon Hunters (Soundtrack from the Netflix Film)',
57+
'The Witcher: Season 2 (Soundtrack from the Netflix Original Series)',
58+
'The White Lotus (Soundtrack from the HBO® Original Limited Series)',
59+
'Inception (Music from the Motion Picture)',
60+
// Releases referring to score instead of soundtrack
61+
'Fantastic Mr. Fox - Additional Music From The Original Score By Alexandre Desplat - The Abbey Road Mixes',
62+
'Scott Pilgrim Vs. The World (Original Score Composed by Nigel Godrich)',
63+
'F1® The Movie (Original Score By Hans Zimmer)',
64+
'EUPHORIA SEASON 2 OFFICIAL SCORE (FROM THE HBO ORIGINAL SERIES)',
65+
'The Bible (Official Score Soundtrack)',
66+
'The Good Wife (The Official TV Score)',
67+
// Releases with OST abbreviation
68+
'O.S.T. Das Boot',
69+
'Alvin & The Chipmunks / OST',
70+
// German release titles
71+
'Get Up (Der Original Soundtrack zum Kinofilm)',
72+
'Ein Mädchen namens Willow - Soundtrack zum Film',
73+
'Das Boot (Soundtrack zur TV Serie, zweite Staffel)',
74+
// Swedish release titles
75+
'Fucking Åmål - Musiken från filmen',
76+
'Fejkpatient (Musik från TV-serien)',
77+
'Kärlek Fårever (Soundtrack till Netflix-filmen)',
78+
// Norwegian release titles
79+
'Kvitebjørn (Musikken fra filmen)',
80+
'Døden på Oslo S (Musikken fra teaterforestillingen)',
81+
// Musical releases
82+
'The Lion King: Original Broadway Cast Recording',
83+
].map((
84+
title,
85+
): FunctionSpec<typeof guessTypesFromTitle>[number] => [
86+
'should detect soundtrack type',
87+
title,
88+
new Set(['Soundtrack']),
89+
])),
4590
];
4691

4792
describe('exact case match', () => {

harmonizer/release_types.ts

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,60 @@ export function guessTypesForRelease(release: HarmonyRelease): Iterable<ReleaseG
1111
return types;
1212
}
1313

14-
const detectTypesPatterns = [
14+
const releaseGroupTypeMatchers: Array<{ type?: ReleaseGroupType; pattern: RegExp }> = [
1515
// Commonly used for Bandcamp releases
16-
/\s\((EP|Single|Live|Demo)\)(?:\s\(.*?\))?$/i,
16+
{ pattern: /\s\((EP|Single|Live|Demo)\)(?:\s\(.*?\))?$/i },
1717
// iTunes singles and EPs
18-
/\s- (EP|Single|Live)(?:\s\(.*?\))?$/i,
18+
{ pattern: /\s- (EP|Single|Live)(?:\s\(.*?\))?$/i },
1919
// Generic "EP" suffix
20-
/\s(EP)(?:\s\(.*?\))?$/i,
20+
{ pattern: /\s(EP)(?:\s\(.*?\))?$/i },
21+
// Common soundtrack title: "Official/Original <Medium> Soundtrack" and "Original Score"
22+
{
23+
type: 'Soundtrack',
24+
pattern:
25+
/(?:Original\s|Official\s)(?:(?:(?:Video\s)?Game|Motion Picture|Film|Movie|Television|TV|(?:(?:TV|Television)[\s-]?)?(?:Mini[\s-]?)?Series?|Musical)[\s-])?(?:Soundtrack|Score)/i,
26+
},
27+
// Common soundtrack title: "Soundtrack from the <Medium>", should also match "Soundtrack from the <Streaming service> <Medium>"
28+
{
29+
type: 'Soundtrack',
30+
pattern:
31+
/(?:Soundtrack|Score|Music)\s(?:(?:from|to) the)\s(?:.+[\s-])?(?:(?:Video\s)?Game|Motion Picture|Film|Movie|(?:(?:TV|Television)[\s-]?)?(?:Mini[\s-]?)?Series|Musical)/i,
32+
},
33+
// Common soundtrack title. Starting or ending with O.S.T. or OST (with or without wrapping parenthesis). Note: it's case sensitive.
34+
{
35+
type: 'Soundtrack',
36+
pattern: /(?:^(?:\(O\.S\.T\.\)|O\.S\.T\.|OST|\(OST\))\s.+|.+\s(?:\(O\.S\.T\.\)|O\.S\.T\.|OST|\(OST\))$)/,
37+
},
38+
// Common musical soundtrack release titles
39+
{ type: 'Soundtrack', pattern: /Original (?:.+\s)?Cast Recording/i },
40+
// Common German soundtrack release titles
41+
{
42+
type: 'Soundtrack',
43+
pattern: /(?:Soundtrack|Musik)\s(?:zum|zur)\s(?:.+[\s-])?(?:(?:Kino)?Film|Theaterstück|(?:TV[\s-]?)?Serie)/i,
44+
},
45+
// Common Swedish soundtrack release titles
46+
{
47+
type: 'Soundtrack',
48+
pattern:
49+
/(?:Soundtrack|Musik(?:en)?)\s(?:från|till|ur)\s(?:.+[\s-])?(?:Film(?:en)?|(?:TV[\s-]?)?(?:Mini[\s-]?)?Serien?|Musikalen)/i,
50+
},
51+
// Common Norwegian soundtrack release titles
52+
{ type: 'Soundtrack', pattern: /Musikk(?:en)? (?:fra) (?:Filmen|TV[\s-]serien|(?:teater)?forestillingen)/i },
2153
];
2254

2355
/** Guesses a release type from a title. */
2456
export function guessTypesFromTitle(title: string): Set<ReleaseGroupType> {
2557
const types = new Set<ReleaseGroupType>();
26-
detectTypesPatterns.forEach((pattern) => {
27-
const match = title.match(pattern);
28-
if (match) {
29-
types.add(capitalizeReleaseType(match[1]));
58+
releaseGroupTypeMatchers.forEach((matcher) => {
59+
const match = title.match(matcher.pattern);
60+
if (!match) {
61+
return;
3062
}
63+
const type = match[1] || matcher.type;
64+
if (!type) {
65+
return;
66+
}
67+
types.add(capitalizeReleaseType(type));
3168
});
3269
return types;
3370
}

0 commit comments

Comments
 (0)