2 Commits
Author SHA1 Message Date
Worph 316db6ad03 add origin
Build and Push Docker Image / build (push) Failing after 13s
2026-09-16 14:55:56 +02:00
Worph c82a931a8c improve search and fix languages
Build and Push Docker Image / build (push) Failing after 13s
2026-09-14 22:29:44 +02:00
2 changed files with 50 additions and 9 deletions
+22 -3
View File
@@ -477,9 +477,21 @@ export function videoSubtitleKeys(produced: ProducedSubtitle[]): Record<string,
return keys; return keys;
} }
/** Keys on the subtitle file's own record. */ /**
* Keys on the subtitle file's own record.
*
* `source/extract` (METADATA_KEYS.md §5) says the bytes came out of a video
* container. The video record already implies it through `extractedSubtitles/`,
* but that is the wrong side of the relation to store it on: a subtitle fetched
* over the swarm by CID arrives WITHOUT its video record, so a reader holding
* only the file would have no way to tell an extracted track from a sidecar
* someone dropped next to the video.
*/
export function subtitleRecordKeys(videoCid: string, lang3: string): Record<string, string> { export function subtitleRecordKeys(videoCid: string, lang3: string): Record<string, string> {
const keys: Record<string, string> = { [`videos/${videoCid}`]: 'true' }; const keys: Record<string, string> = {
[`videos/${videoCid}`]: 'true',
'source/extract': 'true',
};
if (lang3 !== 'und') keys.subtitleLanguage = lang3; if (lang3 !== 'und') keys.subtitleLanguage = lang3;
return keys; return keys;
} }
@@ -499,7 +511,14 @@ export function legacySubtitleMigration(existingMeta: Record<string, unknown> |
const langs = legacyCsvMembers(existingMeta, 'subtitleLanguages'); const langs = legacyCsvMembers(existingMeta, 'subtitleLanguages');
if (langs) { if (langs) {
deletes.push('subtitleLanguages'); deletes.push('subtitleLanguages');
for (const l of langs.map(toLang3)) if (l !== 'und') sets[`subtitleLanguages/${l}`] = 'true'; for (const l of langs.map(toLang3)) {
if (l === 'und') continue;
sets[`subtitleLanguages/${l}`] = 'true';
// …and the union (§9 rule #7). The live write path below already
// does this; the migration path did not, so records that only ever
// went through it were left half-written.
sets[`languages/${l}`] = 'true';
}
} }
const subs = legacyCsvMembers(existingMeta, 'subtitles'); const subs = legacyCsvMembers(existingMeta, 'subtitles');
+28 -6
View File
@@ -284,9 +284,16 @@ describe('record keys (METADATA_KEYS.md §8)', () => {
expect(keys.every((k) => k.split('/').length === 3)).toBe(true); expect(keys.every((k) => k.split('/').length === 3)).toBe(true);
}); });
it('subtitle record carries the back-pointer and a determined language only', () => { it('subtitle record carries the back-pointer, its origin, and a determined language only', () => {
expect(subtitleRecordKeys('bagvideo', 'fre')).toEqual({ 'videos/bagvideo': 'true', subtitleLanguage: 'fre' }); expect(subtitleRecordKeys('bagvideo', 'fre')).toEqual({
expect(subtitleRecordKeys('bagvideo', 'und')).toEqual({ 'videos/bagvideo': 'true' }); 'videos/bagvideo': 'true',
'source/extract': 'true',
subtitleLanguage: 'fre',
});
expect(subtitleRecordKeys('bagvideo', 'und')).toEqual({
'videos/bagvideo': 'true',
'source/extract': 'true',
});
}); });
}); });
@@ -310,7 +317,13 @@ describe('legacySubtitleMigration', () => {
subtitles: 'cidS', subtitles: 'cidS',
})).toEqual({ })).toEqual({
deletes: ['extractedSubtitles', 'subtitleLanguages', 'subtitles'], deletes: ['extractedSubtitles', 'subtitleLanguages', 'subtitles'],
sets: { 'subtitleLanguages/eng': 'true', 'subtitleLanguages/fre': 'true', 'subtitles/und/cidS': 'true' }, sets: {
'subtitleLanguages/eng': 'true',
'languages/eng': 'true',
'subtitleLanguages/fre': 'true',
'languages/fre': 'true',
'subtitles/und/cidS': 'true',
},
}); });
}); });
@@ -495,8 +508,17 @@ describe.skipIf(!ffmpegReady)('process — end to end against a fake core', () =
expect(video.subtitleLanguages).toBeUndefined(); expect(video.subtitleLanguages).toBeUndefined();
expect(video['subtitleLanguages/und']).toBeUndefined(); expect(video['subtitleLanguages/und']).toBeUndefined();
expect(core.records.get(fre)).toEqual({ [`videos/${VIDEO_CID}`]: 'true', subtitleLanguage: 'fre' }); // `source/extract` rides on the subtitle's OWN record, so a peer that
expect(core.records.get(und)).toEqual({ [`videos/${VIDEO_CID}`]: 'true' }); // fetched only the file can still tell it came out of a container.
expect(core.records.get(fre)).toEqual({
[`videos/${VIDEO_CID}`]: 'true',
'source/extract': 'true',
subtitleLanguage: 'fre',
});
expect(core.records.get(und)).toEqual({
[`videos/${VIDEO_CID}`]: 'true',
'source/extract': 'true',
});
// The video PATCH carried only new keys — nothing the record already had. // The video PATCH carried only new keys — nothing the record already had.
const patch = writesTo(core, VIDEO_CID).find((c) => c.method === 'PATCH')!; const patch = writesTo(core, VIDEO_CID).find((c) => c.method === 'PATCH')!;