frontend/index.html (11690 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 name="twitter:card" content="summary"> 14 <meta name="theme-color" content="#4f46e5"> 15 <link rel="stylesheet" href="/style.css?v=12"> 16 <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>"> 17 </head> 18 <body> 19 <header class="topbar"> 20 <div class="brand"> 21 <span class="logo" aria-hidden="true">🎧</span> 22 <div> 23 <h1>SubRead</h1> 24 <p class="tagline">Line an audiobook up with its ebook, sentence by sentence.</p> 25 </div> 26 </div> 27 <div class="account" id="account"> 28 <span id="quota" class="quota" hidden></span> 29 <span id="who" class="who" hidden></span> 30 <button type="button" id="buy-btn" class="ghost compact" hidden>Buy credits</button> 31 <button type="button" id="portal-btn" class="ghost compact" hidden>Manage plan</button> 32 <button type="button" id="signin-btn" class="ghost compact" hidden>Sign in</button> 33 <button type="button" id="signout-btn" class="ghost compact" hidden>Sign out</button> 34 </div> 35 </header> 36 37 <main> 38 <section class="pitch"> 39 <p> 40 Drop in an audiobook and the ebook it was read from. You get back subtitles 41 timed to the narration, with the wording taken from your own book — not 42 from a machine's guess at what it heard. It all happens in this tab: 43 <strong>your files are never uploaded</strong>. 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 <!-- step 1: drop --> 60 <section id="dropzone" class="dropzone" tabindex="0" role="button" 61 aria-label="Drop an audio file and an ebook, or click to choose files"> 62 <input type="file" id="filepicker" multiple hidden 63 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"> 64 <div class="dz-inner"> 65 <div class="dz-icon" aria-hidden="true"> 66 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" 67 stroke-linecap="round" stroke-linejoin="round"> 68 <path d="M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5"/> 69 <path d="M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3"/> 70 </svg> 71 </div> 72 <p class="dz-title" id="dz-title">Drop your audiobook <em>and</em> ebook here</p> 73 <p class="dz-sub" id="dz-sub">One at a time or both at once — order doesn't matter. 74 A folder of per-chapter files works too. 75 Or <button type="button" id="browse" class="linkbtn">browse</button>.</p> 76 <p class="dz-formats">Audio: m4b · mp3 · m4a · opus · flac · wav · mkv 77 | Book: epub · fb2 · mobi · azw3 · txt</p> 78 <p class="dz-formats" id="cover-hint">Optional: drop a jpg or png to use as the 79 video background — <strong>sign in required</strong></p> 80 </div> 81 </section> 82 83 <!-- what has been dropped so far --> 84 <section id="staged" class="panel staged" hidden> 85 <div class="slot" id="slot-audio"> 86 <span class="slot-tick" aria-hidden="true"></span> 87 <div class="slot-body"> 88 <div class="slot-label">Audiobook</div> 89 <div class="slot-value">Waiting for an audio file</div> 90 </div> 91 <button type="button" class="slot-x" data-slot="audio" title="Remove">×</button> 92 </div> 93 <div class="slot" id="slot-cover" hidden> 94 <span class="slot-tick" aria-hidden="true"></span> 95 <div class="slot-body"> 96 <div class="slot-label">Cover image</div> 97 <div class="slot-value">Waiting for an image</div> 98 </div> 99 <button type="button" class="slot-x" data-slot="cover" title="Remove">×</button> 100 </div> 101 <div class="slot" id="slot-text"> 102 <span class="slot-tick" aria-hidden="true"></span> 103 <div class="slot-body"> 104 <div class="slot-label">Book</div> 105 <div class="slot-value">Waiting for an ebook</div> 106 </div> 107 <button type="button" class="slot-x" data-slot="text" title="Remove">×</button> 108 </div> 109 </section> 110 111 <div id="uploading" class="panel uploading" hidden> 112 <div class="spinner" aria-hidden="true"></div> 113 <div class="up-body"> 114 <p class="up-title">Getting ready…</p> 115 <div class="bar"><div id="upbar" class="bar-fill"></div></div> 116 <p id="uptext" class="muted small">0%</p> 117 </div> 118 </div> 119 120 <div id="error" class="panel error" hidden role="alert"></div> 121 122 <!-- step 2: confirm --> 123 <section id="confirm" class="panel confirm" hidden> 124 <h2>Ready to align</h2> 125 <dl class="pairing"> 126 <div><dt>Audiobook</dt><dd id="c-audio"></dd></div> 127 <div><dt>Book</dt><dd id="c-text"></dd></div> 128 </dl> 129 130 <div class="langrow"> 131 <label for="language">Language</label> 132 <select id="language"></select> 133 <span id="detected" class="detected"></span> 134 </div> 135 <p id="splitnote" class="muted small"></p> 136 137 <div id="match" class="match" hidden> 138 <div class="match-head"> 139 <span id="match-badge" class="match-badge"></span> 140 <span id="match-summary"></span> 141 </div> 142 <ul id="match-warnings" class="match-warnings"></ul> 143 </div> 144 145 <div class="mode"> 146 <label class="switch"> 147 <input type="checkbox" id="in-browser" checked> 148 <span>Convert in this browser (JavaScript). Off: our server does it.</span> 149 </label> 150 </div> 151 152 <div class="actions"> 153 <button id="start" class="primary">Start alignment</button> 154 <button id="discard" class="ghost">Discard</button> 155 </div> 156 <p class="muted small" id="eta"></p> 157 </section> 158 159 <!-- step 3: the job, running in this tab --> 160 <section id="working" class="panel working" hidden> 161 <p class="up-title" id="work-title">Starting</p> 162 <div class="bar"><div id="work-bar" class="bar-fill"></div></div> 163 <p id="work-meta" class="muted small"></p> 164 <div class="actions"> 165 <button id="stop" class="ghost">Stop (progress is kept)</button> 166 </div> 167 <div id="results" hidden> 168 <div id="result-files" class="job-files"></div> 169 <p class="muted small">Videos are made here when you ask for them, in seconds. 170 They are not kept anywhere: make them before closing this tab.</p> 171 <p class="muted small" id="chip-in" hidden>SubRead is free, and it has no ads. 172 <a href="https://ko-fi.com/truex" target="_blank" rel="noopener">Chip in for the server on Ko-fi</a>, if it helped.</p> 173 <div class="actions"><button id="another" class="ghost">Convert another book</button></div> 174 </div> 175 </section> 176 177 <!-- step 4: history --> 178 <section id="jobs-section" hidden> 179 <h2 class="section-title">Your conversions</h2> 180 <ul id="jobs" class="jobs"></ul> 181 </section> 182 </main> 183 184 <footer> 185 <p class="muted small"> 186 Alignment method from <a href="https://github.com/kanjieater/SubPlz" target="_blank" rel="noopener">SubPlz</a>; 187 speech model <a href="https://github.com/openai/whisper" target="_blank" rel="noopener">Whisper</a>. 188 Every line of text comes from the book you upload, so names and spelling stay right. 189 </p> 190 <p class="muted small"> 191 <a href="/terms.html">Terms, privacy and refunds</a> · 192 <a href="https://github.com/equwal/subplz-web" target="_blank" rel="noopener">Source code</a> · 193 <a href="https://github.com/equwal/subread-android/releases/latest" target="_blank" rel="noopener">Android app</a> · 194 <a href="https://ko-fi.com/truex" target="_blank" rel="noopener">Support on Ko-fi</a> 195 </p> 196 </footer> 197 198 <dialog id="signin-dialog" class="modal"> 199 <form method="dialog"><button class="modal-x" aria-label="Close">×</button></form> 200 <h2>Sign in</h2> 201 <p class="muted">We email you a one-time link. There is no password.</p> 202 <form id="signin-form" class="signin-form"> 203 <input type="email" id="signin-email" required autocomplete="email" 204 placeholder="you@example.com" aria-label="Email address"> 205 <button class="primary" id="signin-send">Email me a link</button> 206 </form> 207 <p id="signin-note" class="muted small" hidden></p> 208 </dialog> 209 210 <dialog id="share-dialog" class="modal"> 211 <form method="dialog"><button class="modal-x" aria-label="Close">×</button></form> 212 <h2>Share on honjimaku</h2> 213 <p class="muted"><a href="https://honjimaku.com" target="_blank" rel="noopener">honjimaku.com</a> is a free 214 library of subtitles for Japanese audiobooks. Other learners can then read along with this book 215 and do not have to make the subtitles again.</p> 216 <form id="share-form" class="share-form" autocomplete="off"> 217 <label for="share-title">Title of the book, as the audiobook shop writes it</label> 218 <input id="share-title" required maxlength="200"> 219 <label for="share-book-id">Audiobook ID, if there is one (Audible ASIN, audiobook.jp number)</label> 220 <input id="share-book-id" maxlength="40" pattern="[A-Za-z0-9 ._\-]*" placeholder="B0BPXSSWVF"> 221 <label for="share-key">Your honjimaku API key 222 (<a href="https://honjimaku.com/account" target="_blank" rel="noopener">make an account, then "Generate API key"</a>)</label> 223 <input id="share-key" type="password" required autocomplete="off"> 224 <p class="muted small">The key stays in this browser. The subtitles go from this tab to honjimaku.com and to 225 nowhere else. They hold the words of the book: share them only if you may.</p> 226 <button class="primary" id="share-send">Share the subtitles</button> 227 </form> 228 <p id="share-status" class="muted small" hidden></p> 229 </dialog> 230 231 <dialog id="pricing-dialog" class="modal wide"> 232 <form method="dialog"><button class="modal-x" aria-label="Close">×</button></form> 233 <h2>Credits for our server</h2> 234 <p id="pricing-why" class="muted"></p> 235 <div id="plans" class="plans"></div> 236 <p class="muted small" id="pricing-foot"> 237 Paid through Stripe; we never see your card. One credit converts one book 238 on our server, with every output. Credits never expire, and a job that 239 fails gives its credit back. In this tab a conversion is always free. Paying also creates your account, 240 under the email you give Stripe. 241 </p> 242 </dialog> 243 244 <div id="toast" class="toast" hidden role="status"></div> 245 246 <script type="module" src="/app.js?v=12"></script> 247 </body> 248 </html>