Generate Title Card subtitles

This commit is contained in:
Luke Hubmayer-Werner 2024-12-19 18:35:45 +10:30
parent 5927496413
commit af3ab162d4
3 changed files with 53 additions and 16 deletions

View File

@ -11,8 +11,8 @@ const lyrics_output_show_tl_element = document.querySelector('#lyrics_output_sho
const lyrics_output_show_romaji_element = document.querySelector('#lyrics_output_show_romaji');
const lyrics_output_show_kanji_element = document.querySelector('#lyrics_output_show_kanji');
const subtitle_editor_textarea = document.getElementById('subtitle_editor_textarea');
const generate_subtitles = document.getElementById('generate_subtitles');
const download_subtitles = document.getElementById('download_subtitles');
const btn_generate_subtitles = document.getElementById('btn_generate_subtitles');
const btn_download_subtitles = document.getElementById('btn_download_subtitles');
const req_tokenization_url = './tokenize';
// let has_lyrics_changed = false
let tokenized_lyric_lines = [];
@ -223,12 +223,25 @@ document.getElementById('load_song').addEventListener('change', event => {
reader.readAsText(file);
}, false)
download_subtitles.addEventListener('click', () => {
btn_download_subtitles.addEventListener('click', () => {
const song_title_en = document.getElementById('song_title_en').value;
save_text_file(`${song_title_en}.ass`, subtitle_editor_textarea.value);
});
generate_subtitles.addEventListener('click', () => {
import generate_subtitles_from_data from './subtitle_generator.js'
function generate_subtitles() {
console.log('Attempting to generate subtitles');
// TODO: Do something to generate subtitles
const subtitles = generate_subtitles_from_data({
song_title: document.getElementById('song_title').value,
song_title_en: document.getElementById('song_title_en').value,
song_lyricist: document.getElementById('song_lyricist').value,
song_lyricist_en: document.getElementById('song_lyricist_en').value,
song_composer: document.getElementById('song_composer').value,
song_composer_en: document.getElementById('song_composer_en').value,
title_fade_duration_ms: 2500,
});
subtitle_editor_textarea.value = subtitles;
subtitle_editor_textarea.dispatchEvent(new Event('change', {})); // This triggers a reload in the player
});
}
btn_generate_subtitles.addEventListener('click', generate_subtitles);

View File

@ -1,5 +1,9 @@
// This is mostly a port of the python code. It might desync from that over time.
function generate_subtitles() {
function timecode(s) {
return new Date(s*1000).toISOString().substring(11, 22); // This can overflow at 24 hours. Who cares?
}
export default function generate_subtitles_from_data(data) {
const format_defaults = {
'PlayResX': 1280,
'PlayResY': 720,
@ -13,9 +17,10 @@ function generate_subtitles() {
'FuriVMargin': 85,
'KaraokeColourFuture': '000019FF',
'KaraokeColourPast': 'E02A0A00',
'KaraokeColourOutline': 'FFFFFF',
}
const f = format_defaults;
s = `[Script Info]
let s = `[Script Info]
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
@ -25,14 +30,33 @@ PlayResY: ${f.PlayResY}
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,${f.LatinFont},72,&H002A0A00,&H000019FF,&H00FFFFFF,&H00000000,0,0,0,0,100,100,0,0,1,2.5,0,8,30,30,25,1
Style: Kanji,${f.JapaneseFont},${f.KanjiSize},&H${f.KaraokeColourPast},&H${f.KaraokeColourFuture},&H00FFFFFF,&H00000000,0,0,0,0,100,100,0,0,1,4.0,0,2,30,30,${f.KanjiVMargin},1
Style: Furigana,${f.JapaneseFont},${f.FuriSize},&H${f.KaraokeColourPast},&H${f.KaraokeColourFuture},&H00FFFFFF,&H00000000,0,0,0,0,100,100,0,0,1,2.5,0,2,0,0,${f.FuriVMargin},1
Style: Romaji,${f.LatinFont},${f.RomajiSize},&H${f.KaraokeColourPast},&H${f.KaraokeColourFuture},&H00FFFFFF,&H00000000,0,0,0,0,100,100,0,0,1,2.5,0,8,30,30,20,1
Style: Translation,${f.LatinFont},${f.TranslationSize},&H00FFFFFF,&H000019FF,&H00000000,&H00000000,0,1,0,0,100,100,0,0,1,1.0,3,8,30,30,20,1
Style: Default,${f.LatinFont},72,&H2A0A00,&H0019FF,&HFFFFFF,&H000000,0,0,0,0,100,100,0,0,1,2.5,0,8,30,30,25,1
Style: Kanji,${f.JapaneseFont},${f.KanjiSize},&H${f.KaraokeColourPast},&H${f.KaraokeColourFuture},&H${f.KaraokeColourOutline},&H000000,0,0,0,0,100,100,0,0,1,4.0,0,2,30,30,${f.KanjiVMargin},1
Style: Furigana,${f.JapaneseFont},${f.FuriSize},&H${f.KaraokeColourPast},&H${f.KaraokeColourFuture},&H${f.KaraokeColourOutline},&H000000,0,0,0,0,100,100,0,0,1,2.5,0,2,0,0,${f.FuriVMargin},1
Style: Romaji,${f.LatinFont},${f.RomajiSize},&H${f.KaraokeColourPast},&H${f.KaraokeColourFuture},&H${f.KaraokeColourOutline},&H000000,0,0,0,0,100,100,0,0,1,2.5,0,8,30,30,20,1
Style: Translation,${f.LatinFont},${f.TranslationSize},&HFFFFFF,&H0019FF,&H000000,&H000000,0,1,0,0,100,100,0,0,1,1.0,3,8,30,30,20,1
Style: Title,Droid Sans,72,&HFFFFFF,&H0019FF,&H000000,&H000000,0,0,0,0,100,100,0,0,1,2.5,0,3,30,30,25,1
Style: TitleJP,Droid Sans Japanese,72,&HFFFFFF,&H0019FF,&H000000,&H000000,0,0,0,0,100,100,0,0,1,2.5,0,1,30,30,25,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text`
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text`;
// Title card
const t0 = 0.0;
const t1 = 80.0; // TODO: tie this to the first line time
const t0s = timecode(t0);
const t1s = timecode(t1);
const duration_seconds = t1-t0;
const duration_ms = Math.floor(duration_seconds * 1000);
const fade_duration_ms = data.title_fade_duration_ms ?? 1000;
const fade = `{\\fade(255,0,255,0,${fade_duration_ms},${duration_ms-fade_duration_ms},${duration_ms})}`;
s += `
Comment: 0,00:00:00.00,00:01:20.00,,,,,,,Title Card
Dialogue: 0,${t0s},${t1s},TitleJP,,,,,,${fade}作曲 ${data.song_composer}
Dialogue: 0,${t0s},${t1s},TitleJP,,,,,,${fade}作詞 ${data.song_lyricist}
Dialogue: 0,${t0s},${t1s},TitleJP,,,,,,${fade}曲名 ${data.song_title}
Dialogue: 0,${t0s},${t1s},Title,,,,,,${fade}Music: ${data.song_composer_en}
Dialogue: 0,${t0s},${t1s},Title,,,,,,${fade}Lyrics: ${data.song_lyricist_en}
Dialogue: 0,${t0s},${t1s},Title,,,,,,${fade}${data.song_title_en}`;
// TODO: add the lines
return s;
}

View File

@ -136,8 +136,8 @@
<!-- Manual Subtitle Editor -->
<div id="subtitle_editor">
<h2>Subtitle Editor</h2>
<button id="generate_subtitles">Generate Subtitles</button>
<button id="download_subtitles">Download Subtitles</button>
<button id="btn_generate_subtitles">Generate Subtitles</button>
<button id="btn_download_subtitles">Download Subtitles</button>
<br><textarea id="subtitle_editor_textarea" rows="20" cols="80"></textarea>
</div>
</div>