mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-04-07 10:19:22 -07:00
Fix AniList token persistence and AVIF timing
- Defer AniList setup prompts until app-ready and reuse stored tokens - Add AVIF lead-in padding so motion stays aligned with sentence audio
This commit is contained in:
@@ -19,6 +19,7 @@ test('resolveAnimatedImageLeadInSeconds sums configured word audio durations for
|
||||
media: {
|
||||
imageType: 'avif',
|
||||
syncAnimatedImageToWordAudio: true,
|
||||
audioPadding: 0,
|
||||
},
|
||||
},
|
||||
noteInfo: {
|
||||
@@ -49,6 +50,46 @@ test('resolveAnimatedImageLeadInSeconds sums configured word audio durations for
|
||||
assert.equal(leadInSeconds, 1.25);
|
||||
});
|
||||
|
||||
test('resolveAnimatedImageLeadInSeconds adds sentence audio padding to word audio duration', async () => {
|
||||
const leadInSeconds = await resolveAnimatedImageLeadInSeconds({
|
||||
config: {
|
||||
fields: {
|
||||
audio: 'ExpressionAudio',
|
||||
},
|
||||
media: {
|
||||
imageType: 'avif',
|
||||
syncAnimatedImageToWordAudio: true,
|
||||
audioPadding: 0.5,
|
||||
},
|
||||
},
|
||||
noteInfo: {
|
||||
noteId: 42,
|
||||
fields: {
|
||||
ExpressionAudio: {
|
||||
value: '[sound:word.mp3][sound:alt.ogg]',
|
||||
},
|
||||
},
|
||||
},
|
||||
resolveConfiguredFieldName: (noteInfo, ...preferredNames) => {
|
||||
for (const preferredName of preferredNames) {
|
||||
if (!preferredName) continue;
|
||||
const resolved = Object.keys(noteInfo.fields).find(
|
||||
(fieldName) => fieldName.toLowerCase() === preferredName.toLowerCase(),
|
||||
);
|
||||
if (resolved) return resolved;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
retrieveMediaFileBase64: async (filename) =>
|
||||
filename === 'word.mp3' ? 'd29yZA==' : filename === 'alt.ogg' ? 'YWx0' : '',
|
||||
probeAudioDurationSeconds: async (_buffer, filename) =>
|
||||
filename === 'word.mp3' ? 0.41 : filename === 'alt.ogg' ? 0.84 : null,
|
||||
logWarn: () => undefined,
|
||||
});
|
||||
|
||||
assert.equal(leadInSeconds, 1.75);
|
||||
});
|
||||
|
||||
test('resolveAnimatedImageLeadInSeconds falls back to zero when sync is disabled', async () => {
|
||||
const leadInSeconds = await resolveAnimatedImageLeadInSeconds({
|
||||
config: {
|
||||
|
||||
@@ -39,6 +39,14 @@ function shouldSyncAnimatedImageToWordAudio(config: Pick<AnkiConnectConfig, 'med
|
||||
return config.media?.imageType === 'avif' && config.media?.syncAnimatedImageToWordAudio !== false;
|
||||
}
|
||||
|
||||
function resolveSentenceAudioStartOffsetSeconds(config: Pick<AnkiConnectConfig, 'media'>): number {
|
||||
const configuredPadding = config.media?.audioPadding;
|
||||
if (typeof configuredPadding === 'number' && Number.isFinite(configuredPadding)) {
|
||||
return configuredPadding;
|
||||
}
|
||||
return DEFAULT_ANKI_CONNECT_CONFIG.media.audioPadding;
|
||||
}
|
||||
|
||||
export async function probeAudioDurationSeconds(
|
||||
buffer: Buffer,
|
||||
filename: string,
|
||||
@@ -127,5 +135,5 @@ export async function resolveAnimatedImageLeadInSeconds<TNoteInfo extends NoteIn
|
||||
totalLeadInSeconds += durationSeconds;
|
||||
}
|
||||
|
||||
return totalLeadInSeconds;
|
||||
return totalLeadInSeconds + resolveSentenceAudioStartOffsetSeconds(config);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user