Recently Written · git

subplz-web

git clone https://github.com/equwal/subplz-web

Log | Files | Refs


frontend/index.html (14887 bytes)

1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <title>SubRead — read along with your audiobook</title>
7 <meta name="description" content="Line an audiobook up with its ebook, sentence by sentence. Get an SRT for read-along, or a video with subtitles.">
8 <meta property="og:type" content="website">
9 <meta property="og:site_name" content="SubRead">
10 <meta property="og:title" content="SubRead — read along with your audiobook">
11 <meta property="og:description" content="Line an audiobook up with its ebook, sentence by sentence. Get an SRT for read-along, or a video with subtitles.">
12 <meta property="og:url" content="https://subread.space/">
13 <meta property="og:image" content="https://subread.space/og.png">
14 <meta name="twitter:card" content="summary_large_image">
15 <meta name="theme-color" content="#4f46e5">
16 <link rel="stylesheet" href="/style.css?v=13">
17 <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🎧</text></svg>">
18 </head>
19 <body>
20 <header class="topbar">
21   <div class="brand">
22     <span class="logo" aria-hidden="true">🎧</span>
23     <div>
24       <h1>SubRead</h1>
25       <p class="tagline">Line an audiobook up with its ebook, sentence by sentence.</p>
26     </div>
27   </div>
28   <div class="account" id="account">
29     <span id="quota" class="quota" hidden></span>
30     <span id="who" class="who" hidden></span>
31     <button type="button" id="buy-btn" class="ghost compact" hidden>Buy credits</button>
32     <button type="button" id="portal-btn" class="ghost compact" hidden>Manage plan</button>
33     <button type="button" id="signin-btn" class="ghost compact" hidden>Sign in</button>
34     <button type="button" id="signout-btn" class="ghost compact" hidden>Sign out</button>
35   </div>
36 </header>
37 
38 <main>
39   <section class="pitch">
40     <p>
41       Drop in an audiobook and the ebook it was read from. You get back subtitles
42       timed to the narration, with the wording taken from your own book — not
43       from a machine's guess at what it heard. The work happens in this tab, on your computer.
44     </p>
45     <ul class="uses">
46       <li><strong>HoshiReader read-along</strong> — the .srt timing file, to match
47         against your epub. <span class="tag free">free</span></li>
48       <li><strong>Read-along book</strong> — your epub with the narration inside it
49         (EPUB 3 Media Overlays). Thorium, Storyteller and other EPUB 3 readers
50         highlight each line as it is read. <span class="tag free">free</span></li>
51       <li><strong>Local video</strong> — an .mkv with the subtitles built in, for
52         MPV or VLC. <span class="tag free">free</span></li>
53       <li><strong>YouTube video</strong> — a clean .mp4, plus the .srt to upload as
54         its captions. <span class="tag free">free</span></li>
55     </ul>
56     <p class="muted small" id="freetier">Free in your browser, without limit.</p>
57   </section>
58 
59   <!-- where the work is done: in this tab unless the visitor turns it off -->
60   <section id="mode" class="mode">
61     <label class="switch">
62       <input type="checkbox" id="in-browser" checked autocomplete="off">
63       <span><strong>Convert in this browser (JavaScript)</strong>
64         <span class="tag free">free</span></span>
65     </label>
66     <p class="muted small" id="mode-note">The JavaScript version does not use any cloud credits.</p>
67   </section>
68 
69   <!-- step 1: drop -->
70   <section id="dropzone" class="dropzone" tabindex="0" role="button"
71            aria-label="Drop an audio file and an ebook, or click to choose files">
72     <input type="file" id="filepicker" multiple hidden
73            accept=".jpg,.jpeg,.png,.webp,.bmp,.m4b,.m4a,.mp3,.opus,.ogg,.oga,.flac,.wav,.aac,.wma,.mka,.mkv,.mp4,.webm,.avi,.mov,.epub,.txt,.srt,.vtt,.ass,.fb2,.zip,.mobi,.azw,.azw3,.prc">
74     <div class="dz-inner">
75       <div class="dz-icon" aria-hidden="true">
76         <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"
77              stroke-linecap="round" stroke-linejoin="round">
78           <path d="M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5"/>
79           <path d="M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3"/>
80         </svg>
81       </div>
82       <p class="dz-title" id="dz-title">Drop your audiobook <em>and</em> ebook here</p>
83       <p class="dz-sub" id="dz-sub">One at a time or both at once — order doesn't matter.
84         A folder of per-chapter files works too.
85         Or <button type="button" id="browse" class="linkbtn">browse</button>.</p>
86       <p class="dz-formats">Audio: m4b · mp3 · m4a · opus · flac · wav · mkv
87         &nbsp;|&nbsp; Book: epub · fb2 · mobi · azw3 · txt</p>
88       <p class="dz-formats" id="cover-hint">Optional: drop a jpg or png to use as the
89         video background — <strong>sign in required</strong></p>
90     </div>
91   </section>
92 
93   <!-- what has been dropped so far -->
94   <section id="staged" class="panel staged" hidden>
95     <div class="slot" id="slot-audio">
96       <span class="slot-tick" aria-hidden="true"></span>
97       <div class="slot-body">
98         <div class="slot-label">Audiobook</div>
99         <div class="slot-value">Waiting for an audio file</div>
100       </div>
101       <button type="button" class="slot-x" data-slot="audio" title="Remove">×</button>
102     </div>
103     <div class="slot" id="slot-cover" hidden>
104       <span class="slot-tick" aria-hidden="true"></span>
105       <div class="slot-body">
106         <div class="slot-label">Cover image</div>
107         <div class="slot-value">Waiting for an image</div>
108       </div>
109       <button type="button" class="slot-x" data-slot="cover" title="Remove">×</button>
110     </div>
111     <div class="slot" id="slot-text">
112       <span class="slot-tick" aria-hidden="true"></span>
113       <div class="slot-body">
114         <div class="slot-label">Book</div>
115         <div class="slot-value">Waiting for an ebook</div>
116       </div>
117       <button type="button" class="slot-x" data-slot="text" title="Remove">×</button>
118     </div>
119   </section>
120 
121   <div id="uploading" class="panel uploading" hidden>
122     <div class="spinner" aria-hidden="true"></div>
123     <div class="up-body">
124       <p class="up-title">Getting ready…</p>
125       <div class="bar"><div id="upbar" class="bar-fill"></div></div>
126       <p id="uptext" class="muted small">0%</p>
127     </div>
128   </div>
129 
130   <div id="error" class="panel error" hidden role="alert"></div>
131 
132   <!-- step 2: confirm -->
133   <section id="confirm" class="panel confirm" hidden>
134     <h2>Ready to align</h2>
135     <dl class="pairing">
136       <div><dt>Audiobook</dt><dd id="c-audio"></dd></div>
137       <div><dt>Book</dt><dd id="c-text"></dd></div>
138     </dl>
139 
140     <div class="langrow">
141       <label for="language">Language</label>
142       <select id="language"></select>
143       <span id="detected" class="detected"></span>
144     </div>
145     <p id="splitnote" class="muted small"></p>
146 
147     <div id="match" class="match" hidden>
148       <div class="match-head">
149         <span id="match-badge" class="match-badge"></span>
150         <span id="match-summary"></span>
151       </div>
152       <ul id="match-warnings" class="match-warnings"></ul>
153     </div>
154 
155     <div class="actions">
156       <button id="start" class="primary">Start alignment</button>
157       <button id="discard" class="ghost">Discard</button>
158     </div>
159     <p class="muted small" id="eta"></p>
160   </section>
161 
162   <!-- step 3: the job, running in this tab -->
163   <section id="working" class="panel working" hidden>
164     <p class="up-title" id="work-title">Starting</p>
165     <div class="bar"><div id="work-bar" class="bar-fill"></div></div>
166     <p id="work-meta" class="muted small"></p>
167     <div class="actions">
168       <button id="stop" class="ghost">Stop (progress is kept)</button>
169     </div>
170     <div id="results" hidden>
171       <div id="result-files" class="job-files"></div>
172       <p class="muted small">Videos are made here when you ask for them, in seconds.
173         They are not kept anywhere: make them before closing this tab.</p>
174       <p class="muted small" id="chip-in" hidden>SubRead is free, and it has no ads.
175         <a href="https://ko-fi.com/truex" target="_blank" rel="noopener">Chip in for the server on Ko-fi</a>, if it helped.</p>
176       <div class="actions"><button id="another" class="ghost">Convert another book</button></div>
177     </div>
178   </section>
179 
180   <!-- step 4: history -->
181   <section id="jobs-section" hidden>
182     <h2 class="section-title">Your conversions</h2>
183     <ul id="jobs" class="jobs"></ul>
184   </section>
185 </main>
186 
187 <footer>
188   <p class="muted small">
189     Alignment method from <a href="https://github.com/kanjieater/SubPlz" target="_blank" rel="noopener">SubPlz</a>;
190     speech model <a href="https://github.com/openai/whisper" target="_blank" rel="noopener">Whisper</a>.
191     Every line of text comes from the book you upload, so names and spelling stay right.
192   </p>
193   <p class="muted small">
194     <a href="/terms.html">Terms, privacy and refunds</a> ·
195     <a href="https://github.com/equwal/subread-android/releases/latest" target="_blank" rel="noopener">Android app</a> ·
196     <a href="https://ko-fi.com/truex" target="_blank" rel="noopener">Support on Ko-fi</a>
197   </p>
198   <nav class="muted small" aria-label="More sites and apps">
199     <p>More sites and apps:
200       <a href="https://booksimulator.com/" target="_blank" rel="noopener" title="A reading room for Aozora Bunko and Project Gutenberg books.">Book Simulator</a> ·
201       <a href="https://honjimaku.com/" target="_blank" rel="noopener" title="Subtitles for Japanese audiobooks.">honjimaku.com</a> ·
202       <a href="https://sbmsync.com/" target="_blank" rel="noopener" title="Your bookmarks, the same on every device.">sbm Sync</a> ·
203       <a href="https://dickt.store/" target="_blank" rel="noopener" title="Language-learning tools, flashcards and web toys.">dickt.store</a> ·
204       <a href="https://hentaibun.online/" target="_blank" rel="noopener" title="Learn kanbun and kobun.">hentaibun.online</a> ·
205       <a href="https://mowimypopol.online/" target="_blank" rel="noopener" title="Archival study materials for Polish.">mowimypopol.online</a> ·
206       <a href="https://alljapanesealltheti.me/" target="_blank" rel="noopener" title="All Japanese All The Time.">AJATT mirror</a> ·
207       <a href="https://recentlywritten.com/" target="_blank" rel="noopener" title="The blog.">Recently Written</a>
208     </p>
209     <p>Apps:
210       <a href="https://github.com/equwal/subread-overlay/releases/latest" target="_blank" rel="noopener">SubRead Overlay</a> ·
211       <a href="https://github.com/equwal/subread-dictionary/releases/latest" target="_blank" rel="noopener">SubRead Dictionary</a> ·
212       <a href="https://github.com/equwal/subread-anki" target="_blank" rel="noopener">SubRead Anki</a> ·
213       <a href="https://github.com/equwal/subread-extension/releases/latest" target="_blank" rel="noopener">SubRead for YouTube</a> ·
214       <a href="https://github.com/equwal/subread.koplugin" target="_blank" rel="noopener">SubRead for KOReader</a> ·
215       <a href="https://github.com/equwal/subrep-android/releases/latest" target="_blank" rel="noopener">Subrep</a> ·
216       <a href="https://github.com/equwal/sbm-android/releases/latest" target="_blank" rel="noopener">sbm for Android</a> ·
217       <a href="https://github.com/equwal/sbm-extension/releases/latest" target="_blank" rel="noopener">sbm add-on</a> ·
218       <a href="https://github.com/equwal/rebind/releases" target="_blank" rel="noopener">Rebind</a> ·
219       <a href="https://github.com/equwal/ink-recents/releases/latest" target="_blank" rel="noopener">Ink Recents</a> ·
220       <a href="https://github.com/equwal/ink-dim/releases/latest" target="_blank" rel="noopener">Ink Dim</a> ·
221       <a href="https://github.com/equwal/ink-update/releases/latest" target="_blank" rel="noopener">Ink Update</a> ·
222       <a href="https://recentlywritten.com/projects.html" target="_blank" rel="noopener">All projects</a>
223     </p>
224   </nav>
225 </footer>
226 
227 <dialog id="signin-dialog" class="modal">
228   <form method="dialog"><button class="modal-x" aria-label="Close">×</button></form>
229   <h2>Sign in</h2>
230   <p class="muted">We email you a one-time link. There is no password.</p>
231   <form id="signin-form" class="signin-form">
232     <input type="email" id="signin-email" required autocomplete="email"
233            placeholder="you@example.com" aria-label="Email address">
234     <button class="primary" id="signin-send">Email me a link</button>
235   </form>
236   <p id="signin-note" class="muted small" hidden></p>
237 </dialog>
238 
239 <dialog id="share-dialog" class="modal">
240   <form method="dialog"><button class="modal-x" aria-label="Close">×</button></form>
241   <h2>Share on honjimaku</h2>
242   <p class="muted"><a href="https://honjimaku.com" target="_blank" rel="noopener">honjimaku.com</a> is a free
243     library of subtitles for Japanese audiobooks. Other learners can then read along with this book
244     and do not have to make the subtitles again.</p>
245   <form id="share-form" class="share-form" autocomplete="off">
246     <label for="share-title">Title of the book, as the audiobook shop writes it</label>
247     <input id="share-title" required maxlength="200">
248     <label for="share-book-id">Audiobook ID, if there is one (Audible ASIN, audiobook.jp number)</label>
249     <input id="share-book-id" maxlength="40" pattern="[A-Za-z0-9 ._\-]*" placeholder="B0BPXSSWVF">
250     <label for="share-key">Your honjimaku API key
251       (<a href="https://honjimaku.com/account" target="_blank" rel="noopener">make an account, then "Generate API key"</a>)</label>
252     <input id="share-key" type="password" required autocomplete="off">
253     <p class="muted small">The key stays in this browser. The subtitles go from this tab to honjimaku.com and to
254       nowhere else. They hold the words of the book: share them only if you may.</p>
255     <button class="primary" id="share-send">Share the subtitles</button>
256   </form>
257   <p id="share-status" class="muted small" hidden></p>
258 </dialog>
259 
260 <dialog id="pricing-dialog" class="modal wide">
261   <form method="dialog"><button class="modal-x" aria-label="Close">×</button></form>
262   <h2>Credits for our server</h2>
263   <p id="pricing-why" class="muted"></p>
264   <p id="pricing-signin" hidden><button type="button" id="pricing-signin-btn" class="linkbtn"></button></p>
265   <div id="plans" class="plans"></div>
266   <p class="muted small" id="pricing-foot">
267     Paid through Stripe; we never see your card. One credit converts one book
268     on our server, with every output. Credits in a pack never expire, and a job that
269     fails gives its credit back. A monthly plan renews each month until you cancel it
270     with "Manage plan"; its books do not carry over to the next month. In this tab a
271     conversion is always free. Paying also creates your account, under the email you give Stripe.
272   </p>
273 </dialog>
274 
275 <div id="toast" class="toast" hidden role="status"></div>
276 
277 <script type="module" src="/app.js?v=13"></script>
278 </body>
279 </html>