├── .github └── CODEOWNERS ├── .gitignore ├── README.md ├── nico_downloader ├── LICENSE ├── dic_scripts.js ├── dist │ ├── ffmpeg-core.wasm │ ├── ffmpeg-core2.js │ └── utils.js ├── func │ ├── ndl.js │ └── nicojson.js ├── icon_128.png ├── icon_16.png ├── icon_48.png ├── manifest.json ├── nicovideodownloader_scripts.js ├── options.html ├── options.js └── options_menu.js └── tool ├── actionTrackId_make.js ├── api.nico ├── newhls_encode.js ├── old.js └── options.html /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # レビュアーに指定 2 | * @masteralice304 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | test -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nico downloader 2 | 3 | nico downloader:ニコニコ用のシンプルなChrome拡張 4 | 5 | **Chrome Webストアで公開されています!** 6 | 7 | **https://chromewebstore.google.com/detail/nico-downloader/dncjcadpoakefjpnabimpalenliehbig** 8 | 9 | --- 10 | 11 | - [nico downloader](#nico-downloader) 12 | - [コンセプト](#コンセプト) 13 | - [おことわりと怒りの表明](#おことわりと怒りの表明) 14 | - [要件](#要件) 15 | - [初期設定](#初期設定) 16 | - [使用方法](#使用方法) 17 | - [しくみ](#しくみ) 18 | - [QandAや要望](#qandaや要望) 19 | - [非常に雑なリリースノート](#非常に雑なリリースノート) 20 | 21 | 22 | ## コンセプト 23 | - 動画ページでの保存ボタンの自動作成 24 | - 動画結合処理の実装 25 | - シンプルな機能とある程度のカスタマイズ性の両立 26 | - mp4/aacに対応 27 | 28 | ## おことわりと怒りの表明 29 | 1. 基本的にsm~以外の動画では動作しないようにしてあります 30 | 1. 一部の動画に暗号化されている動画がありますが、いろいろなところに抵触する為対応しません 31 | 1. 絶対に邪な使い方はしないで下さい 32 | 2. しょぼいスペックのPCではまず動きません  33 | 34 | ## 要件 35 | | 区分 | 数値 | 備考 | 36 | | :--------------- | :------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | 37 | | CPU | AMD Ryzen Zen プロセッサより新しいプロセッサ | | 38 | | RAM | 16GB以上 | 16GB未満はサポート対象外
変換前にメモリ上に保存する関係でメモリを大量に使用
動画1時間あたり約4GBのメモリ消費を想定 | 39 | | OS | Windows 11 23H2以上 | Macintoshは一切の動作保証なし | 40 | | 導入するブラウザ | Chrome最新版 | Chrome以外はサポート対象外(特にEdge) | 41 | | 回線 | 100Mbps以上
nicovideo.jpへのpingやfetchの疎通が常にうまくいく環境 | これ未満でも動かないということはないが、自己責任でお願いします | 42 | 43 | 44 | ## 初期設定 45 | 1. Chromeの拡張機能の設定であったり、右上のボタンを押すなりしてオプションを開きます 46 | 2. 初期設定モードをOFFにします 47 | 3. 一番下の保存ボタンを押します 48 | 4. これで完了です 49 | 50 | ## 使用方法 51 | 1. 動画ページを開く 52 | 1. 基本的にsm~から始まる動画のみサポート 53 | 1. それ以外の動画は動作サポート対象外 54 | 1. 2秒くらい待つ 55 | 1. 動画の右下あたりに「保存」ボタンが生成ささる 56 | 1. クリックされるとシステムメッセージが自動で開かさり処理開始される 57 | 1. 開かれたシステムメッセージはすぐ閉じて大丈夫です 58 | 1. 処理は自動で行われる 59 | 1. ffmpegが裏で処理を行っているので少々重いかもしれない 60 | 1. 保存ダイアログが出るか既定のフォルダに保存される 61 | 1. ここはChromeの設定に依存するため注意を要する 62 | 63 | ## しくみ 64 | 1. 動画ページのシステムメッセージ内にHLSのURLがあるので、そのURLを抽出しそのデータをキャッシュ 65 | 1. 同様に、動画のタイトルを抽出しそのデータをキャッシュ 66 | 1. キャッシュされたデータをもとにCMAFとかを取得 67 | 1. 取得したデータをffmpeg.wasmで結合(aacの場合、aacで出力、mp4の場合mp4で出力) 68 | 1. 結合したデータをblobとして取得 69 | 1. すでにblobになっているのでディスクに書き込めばすぐ保存終了 70 | 71 | ## QandAや要望 72 | | 質問 | 回答 | 73 | | :----------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 74 | | 1. 保存できる画質を設定できるようにしてほしい | <対応予定あり>時間要します | 75 | | 2. 音声データを保存できるようにしてほしい | プルリクを採用し対応しました。→[対応させていただきました](https://github.com/masteralice3104/nico_downloader/pull/8) | 76 | | 3. コメントをダウンロードできるようにしてほしい | <対応検討中> | 77 | | 4. ダウンロードしようとしたら1KBになりました。バグらささっていると思います。 | 十中八九変換に失敗しています。
原因の一例
・PCのメモリが足りない(要件を読んで下さい)
・回線の問題でダウンロードに失敗した(要件を読んで下さい)
・動画が暗号化されている(おことわりを読んで下さい)
・動画が長すぎる(特に3時間以上) | 78 | | 5. バグを発見した | Issuesを立ててください | 79 | | 6. Plz, I've Question by ENG or other... | I understand "Japanese". But I can't understand enough ENG. ------ I'd confirmed that DeepL translation and Google Translate don't correctly translate the dialect I talk. These sentence is also likely to be incorrect. Therefore, if you and I use a translator, our intentions would may be conveyed incorrectly. So I can't respond. | 80 | | 7. 多言語対応してほしい | 一応多言語対応できる状態になっていますがそもそも正しい翻訳なのかかなり怪しい状況です | 81 | | 8. 「あ、 nico downloaderの現状、不具合、リリースノートなどはこちらから のリンク先がなくなってます」 | 直しました。2024.9.16 | 82 | | 9. なんか良さげな改造した!見て! | プルリクください。変更点をすべて確認した後、採用する場合があります。 | 83 | | 10. バージョンが細かすぎるのでは? | Chrome Web Storeの審査に時間をかけないための工夫です。 | 84 | | | 85 | 86 | ## 非常に雑なリリースノート 87 | | バージョン名 | 日次 | アップデート項目 | 88 | | ------------ | ---------- | ------------------------------------------------------------------------ | 89 | | 1.0.0.0 | 覚えてない | リリース前バージョン 初作成 | 90 | | 1.0.2.2 | | リリース | 91 | | 1.0.2.3 | | リファクタリング及びバグの修正 | 92 | | 1.0.2.4 | | デバッグモードの実装 | 93 | | 1.1.0.0 | | ニコニコ大百科用の機能追加 | 94 | | 1.2.0.0 | 2022.3.14 | 自動保存モード追加
setOption修正 | 95 | | 1.2.0.1 | 2022.6.18 | nm番号のものがDLできなかった件修正 | 96 | | 2.0.0.0 | 2023.6.1 | HLSモード対応
外部のffmpeg.exeを使用したバージョン | 97 | | 3.0.0.0 | 2023.6.13 | HLSモードをffmpeg.wasmを使ったものに変更 | 98 | | 3.0.0.1 | 2023.6.18 | 修正 | 99 | | 3.0.0.2 | 2023.11.1 | ニコニコの突然のUI変更に対応 | 100 | | 4.0.0.0 | 2023.12.3 | 大規模なリファクタリングにて再構築 | 101 | | 4.1.0.0 | 2024.8.5 | リファクタリング | 102 | | 5.0.0.0 | 2024.8.5 | 帰ってきたニコニコ対応 | 103 | | 5.0.0.1 | 2024.8.7 | 保存時メモリを大量に使う問題に対処 | 104 | | 5.0.0.2 | 2024.8.7 | 二重ダウンロードされることがある問題に対処 | 105 | | 5.0.0.3 | 2024.8.10 | 初期設定モードの説明が変なことになっていたのを修正 | 106 | | 5.0.0.4 | 2024.8.11 | リファクタリング | 107 | | 5.0.0.5 | 2024.8.11 | オプション画面を書き換え | 108 | | 5.0.0.6 | 2024.9.6 | 誤字修正、ニコニコの動画ページ変更追従 | 109 | | 5.0.0.7 | 2024.9.16 | 多言語対応の設定を追加
オプションページの変更 | 110 | | 5.0.0.8 | 2024.9.17 | 保存された動画への一部メタタグの追加 | 111 | | 5.0.0.9 | 2024.9.23 | 軽微な修正 | 112 | | 5.0.0.10 | 2024.9.26 | 5.0.0.7へのロールバック | 113 | | 5.0.0.11 | 2024.9.27 | シリーズが存在しない動画の場合途中で落ちる現象の修正、微修正 | 114 | | 5.0.0.13 | 2024.9.28 | 投稿者が存在しない動画への対処 | 115 | | 5.0.0.14 | 2024.11.4 | aacに対応( https://github.com/masteralice3104/nico_downloader/pull/8 ) | 116 | | 5.0.0.15 | 2024.11.4 | タグなし動画の場合途中で落ちる現象の修正 | 117 | | 5.0.0.16 | 2025.02.22 | ニコニコの画面更新に対応 | 118 | | 5.0.0.17 | 2025.02.22 | オプション初期処理が抜けていたのを修正 | 119 | | 5.0.0.18 | 2025.02.24 | モードが取得できなかった場合はデフォルトのmp4にする仕組み導入 | -------------------------------------------------------------------------------- /nico_downloader/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 masteralice3104 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /nico_downloader/dic_scripts.js: -------------------------------------------------------------------------------- 1 | let start_res = 0; 2 | let end_res = 0; 3 | 4 | 5 | 6 | //ページ表示時発火処理 7 | window.onload = function () { 8 | Start_Dic(); 9 | } 10 | 11 | function Start_Dic() { 12 | const thisURL = location.href; 13 | 14 | 15 | 16 | 17 | //スレのみページ 18 | if (thisURL.match("https://dic.nicovideo.jp/b/a/.")) { 19 | 20 | refresh_resNo(); 21 | 22 | 23 | //html要素作成 24 | let button_threadnext = document.createElement('button'); 25 | button_threadnext.id = `next_30`; 26 | button_threadnext.innerHTML = `次の30件を読込`; 27 | if (end_res % 30 == 0) { 28 | document.getElementsByClassName("st-bbs_resbody")[document.getElementsByClassName("st-bbs_resbody").length - 1].after(button_threadnext); 29 | document.getElementById("next_30").onclick = next_30load; 30 | } 31 | 32 | let button_threadprev = document.createElement('button'); 33 | button_threadprev.id = `prev_30`; 34 | button_threadprev.innerHTML = `前の30件を読込`; 35 | if (start_res != 0) { 36 | document.getElementsByClassName("st-bbs_reshead")[0].before(button_threadprev); 37 | document.getElementById("prev_30").onclick = prev_30load; 38 | } 39 | 40 | resnumhead_plus(); 41 | 42 | pinres(); 43 | 44 | 45 | } 46 | if (thisURL.match("https://dic.nicovideo.jp/a/.")) { 47 | pinres(); 48 | } 49 | 50 | } 51 | 52 | function pinres() { 53 | 54 | let button_threadpin1 = document.createElement('button'); 55 | button_threadpin1.id = `threadpin_move_button1`; 56 | button_threadpin1.innerText = `最後に記録したレスに移動`; 57 | 58 | let button_threadpin2 = document.createElement('button'); 59 | button_threadpin2.id = `threadpin_move_button2`; 60 | button_threadpin2.innerText = `最後に記録したレスに移動`; 61 | 62 | if (setOption(kiji_URL_get())) { 63 | document.getElementsByClassName("st-bbs_reshead")[0].before(button_threadpin1); 64 | document.getElementById("threadpin_move_button1").onclick = threadpin_move; 65 | document.getElementsByClassName("st-bbs_resbody")[document.getElementsByClassName("st-bbs_resbody").length - 1].after(button_threadpin2); 66 | document.getElementById("threadpin_move_button2").onclick = threadpin_move2; 67 | DebugPrint("threadpin_move set") 68 | } else { 69 | 70 | } 71 | } 72 | 73 | function refresh_resNo() { 74 | if (document.getElementsByClassName("st-bbs_resNo")) { 75 | //ページ最初と最後のレス番号取得 76 | start_res = Number(document.getElementsByClassName("st-bbs_resNo")[0].innerHTML); 77 | end_res = Number(document.getElementsByClassName("st-bbs_resNo")[document.getElementsByClassName("st-bbs_resNo").length - 1].innerHTML) 78 | DebugPrint(start_res + "~" + end_res); 79 | } 80 | } 81 | 82 | 83 | function prev_30load() { 84 | 85 | document.getElementById("prev_30").setAttribute("disabled", true); 86 | 87 | 88 | let kijiURL = kiji_URL_get(); 89 | let DL_URL = kijiURL + "/" + Number(start_res - 30) + "-" 90 | DebugPrint(DL_URL); 91 | 92 | if (start_res != 1) { 93 | //https://www.codit.work/notes/ld2h3c2k1coufqauzydl/ を参考にした 94 | const result = fetch(DL_URL, { 95 | method: "GET" 96 | }).then(function (response) { 97 | return response.text(); 98 | }).then(function (data) { 99 | const parser = new DOMParser(); 100 | const doc = parser.parseFromString(data, "text/html"); 101 | 102 | //中身取得 103 | let res_head = doc.getElementsByClassName("st-bbs_reshead"); 104 | let res_body = doc.getElementsByClassName("st-bbs_resbody"); 105 | let res_num = doc.getElementsByClassName("st-bbs_resbody").length; 106 | 107 | //htmlに追加 108 | //ここがちょっと違う 109 | for (let i = res_num - 1; i >= 0; i--) { 110 | let add_element = createElementFromHTML(res_head[i].outerHTML); 111 | document.getElementsByClassName("st-bbs_reshead")[0].before(add_element) 112 | 113 | add_element = createElementFromHTML(res_body[i].outerHTML); 114 | document.getElementsByClassName("st-bbs_reshead")[0].after(add_element) 115 | } 116 | 117 | //番号更新 118 | refresh_resNo(); 119 | 120 | if (start_res != 1) { } else { 121 | document.getElementById("prev_30").remove(); 122 | 123 | let last_element = document.createElement('p'); 124 | last_element.innerText = "最初のレスまで読み込みました"; 125 | document.getElementsByClassName("st-bbs_reshead")[0].before(last_element); 126 | } 127 | document.getElementById("prev_30").removeAttribute("disabled"); 128 | resnumhead_plus(); 129 | }); 130 | 131 | } 132 | } 133 | 134 | function next_30load() { 135 | 136 | document.getElementById("next_30").setAttribute("disabled", true); 137 | 138 | let kijiURL = kiji_URL_get(); 139 | let DL_URL = kijiURL + "/" + Number(end_res + 1) + "-" 140 | DebugPrint(DL_URL); 141 | 142 | if (end_res % 30 == 0) { 143 | //https://www.codit.work/notes/ld2h3c2k1coufqauzydl/ を参考にした 144 | const result = fetch(DL_URL, { 145 | method: "GET" 146 | }).then(function (response) { 147 | return response.text(); 148 | }).then(function (data) { 149 | const parser = new DOMParser(); 150 | const doc = parser.parseFromString(data, "text/html"); 151 | 152 | //中身取得 153 | let res_head = doc.getElementsByClassName("st-bbs_reshead"); 154 | let res_body = doc.getElementsByClassName("st-bbs_resbody"); 155 | let res_num = doc.getElementsByClassName("st-bbs_resbody").length; 156 | 157 | //htmlに追加 158 | for (let i = 0; i < res_num; i++) { 159 | let add_element = createElementFromHTML(res_head[i].outerHTML); 160 | document.getElementsByClassName("st-bbs_resbody")[document.getElementsByClassName("st-bbs_resbody").length - 1].after(add_element) 161 | 162 | add_element = createElementFromHTML(res_body[i].outerHTML); 163 | document.getElementsByClassName("st-bbs_reshead")[document.getElementsByClassName("st-bbs_reshead").length - 1].after(add_element) 164 | } 165 | 166 | //番号更新 167 | refresh_resNo(); 168 | 169 | 170 | 171 | if (end_res % 30 == 0) { 172 | document.getElementById("next_30").removeAttribute("disabled"); 173 | } else { 174 | document.getElementById("next_30").remove(); 175 | 176 | let last_element = document.createElement('p'); 177 | last_element.innerText = "最新のレスまで読み込みました"; 178 | document.getElementsByClassName("st-bbs_resbody")[document.getElementsByClassName("st-bbs_resbody").length - 1].after(last_element); 179 | 180 | } 181 | resnumhead_plus(); 182 | }); 183 | 184 | } 185 | } 186 | 187 | 188 | 189 | 190 | 191 | //https://qiita.com/seijikohara/items/911f886d8eb79862870b 192 | //ぶちこんだHTMLをelementにして返す 193 | function createElementFromHTML(html) { 194 | const tempEl = document.createElement('div'); 195 | tempEl.innerHTML = html; 196 | return tempEl.firstElementChild; 197 | } 198 | 199 | //元記事URL取得 200 | function kiji_URL_get() { 201 | let href = document.getElementsByClassName("st-pg_navi")[0].href; 202 | href = href.replace("https://dic.nicovideo.jp/a/", "https://dic.nicovideo.jp/b/a/") 203 | return href; 204 | } 205 | 206 | 207 | function resnumhead_plus() { 208 | DebugPrint("resnumhead_plus"); 209 | for (let i = 0; i < document.getElementsByClassName("resnumhead").length; i++) { 210 | 211 | if (setOption(kiji_URL_get())) { 212 | if (setOption(kiji_URL_get()) === document.getElementsByClassName("resnumhead")[i].getAttribute("name")) { 213 | document.getElementsByClassName("resnumhead")[i].innerText = "■"; 214 | } else { 215 | document.getElementsByClassName("resnumhead")[i].innerText = "□"; 216 | } 217 | } else { 218 | document.getElementsByClassName("resnumhead")[i].innerText = "□"; 219 | } 220 | document.getElementsByClassName("resnumhead")[i].href = "javascript:void(0);" 221 | document.getElementsByClassName("resnumhead")[i].onclick = pin_dome; 222 | document.getElementsByClassName("resnumhead")[i].id = document.getElementsByClassName("resnumhead")[i].getAttribute("name"); 223 | 224 | } 225 | } 226 | 227 | function pin_dome(e) { 228 | let res_no = e.currentTarget.getAttribute("name"); 229 | let kiji_URL = kiji_URL_get(); 230 | DebugPrint("pin_dome : " + kiji_URL + " : " + res_no); 231 | 232 | 233 | 234 | //変更 235 | if (e.currentTarget.innerText === "■") { 236 | //ローカルストレージを0で上書き 237 | Option_setWriting(kiji_URL, "0"); 238 | //e.currentTarget.innerText = "□"; 239 | } else { 240 | //ローカルストレージに書き込み 241 | Option_setWriting(kiji_URL, res_no); 242 | //e.currentTarget.innerText = "■"; 243 | } 244 | resnumhead_plus(); 245 | 246 | } 247 | 248 | function threadpin_move2() { 249 | threadpin_move() 250 | } 251 | 252 | function threadpin_move() { 253 | 254 | DebugPrint("threadpin_move") 255 | let kiji_URL = kiji_URL_get(); 256 | let id = Number(setOption(kiji_URL)); 257 | if (id === 0) { 258 | let defaultURL = kiji_URL + "/1-"; 259 | location.href = defaultURL; 260 | } 261 | 262 | if (start_res <= id && end_res >= id) { 263 | location.hash = ""; 264 | location.hash = id.toString(); 265 | return; 266 | } 267 | 268 | 269 | let page = Math.floor(id / 30) * 30 + 1; 270 | let pageURL = kiji_URL + "/" + page; 271 | 272 | if (start_res > id | start_res === 0) { 273 | setTimeout(threadpin_move, 200); 274 | location.href = pageURL + "#" + id.toString(); 275 | 276 | 277 | 278 | // document.getElementById("prev_30").click(); 279 | 280 | 281 | } 282 | if (end_res < id | end_res === 0) { 283 | // document.getElementById("next_30").click(); 284 | setTimeout(threadpin_move, 200); 285 | location.href = pageURL + "#" + id.toString(); 286 | 287 | 288 | } 289 | 290 | } -------------------------------------------------------------------------------- /nico_downloader/dist/ffmpeg-core.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/masteralice3104/nico_downloader/a4fac44a27252a09b070d11464c3b68ab9c5fe96/nico_downloader/dist/ffmpeg-core.wasm -------------------------------------------------------------------------------- /nico_downloader/dist/ffmpeg-core2.js: -------------------------------------------------------------------------------- 1 | 2 | var createFFmpegCore = (function() { 3 | var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; 4 | if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; 5 | return ( 6 | function(createFFmpegCore) { 7 | createFFmpegCore = createFFmpegCore || {}; 8 | 9 | 10 | var e;e||(e=typeof createFFmpegCore !== 'undefined' ? createFFmpegCore : {});var ba,ca;e.ready=new Promise(function(a,b){ba=a;ca=b});e.quit=function(a){if(e.onExit)e.onExit(a);throw new da(a);};e.exit=ea;fa=k=function(){};var ia={},ja;for(ja in e)e.hasOwnProperty(ja)&&(ia[ja]=e[ja]);var ka=[],la="./this.program";function ma(a,b){throw b;}var na=!1,pa=!1,qa=!1,ra=!1;na="object"===typeof window;pa="function"===typeof importScripts; 11 | qa="object"===typeof process&&"object"===typeof process.versions&&"string"===typeof process.versions.node;ra=!na&&!qa&&!pa;var l="",sa,ta,ua,va; 12 | if(qa)l=pa?require("path").dirname(l)+"/":__dirname+"/",sa=function(a,b){ua||(ua=require("fs"));va||(va=require("path"));a=va.normalize(a);return ua.readFileSync(a,b?null:"utf8")},ta=function(a){a=sa(a,!0);a.buffer||(a=new Uint8Array(a));assert(a.buffer);return a},1=d);)++c;if(16f?d+=String.fromCharCode(f):(f-=65536,d+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else d+=String.fromCharCode(f)}return d}function z(a,b){return a?Fa(B,a,b):""} 19 | function Ga(a,b,c,d){if(!(0=h){var m=a.charCodeAt(++g);h=65536+((h&1023)<<10)|m&1023}if(127>=h){if(c>=d)break;b[c++]=h}else{if(2047>=h){if(c+1>=d)break;b[c++]=192|h>>6}else{if(65535>=h){if(c+2>=d)break;b[c++]=224|h>>12}else{if(c+3>=d)break;b[c++]=240|h>>18;b[c++]=128|h>>12&63}b[c++]=128|h>>6&63}b[c++]=128|h&63}}b[c]=0;return c-f}function Da(a,b,c){return Ga(a,B,b,c)} 20 | function Ha(a){for(var b=0,c=0;c=d&&(d=65536+((d&1023)<<10)|a.charCodeAt(++c)&1023);127>=d?++b:b=2047>=d?b+2:65535>=d?b+3:b+4}return b}function Ja(a){var b=Ha(a)+1,c=Ka(b);c&&Ga(a,x,c,b);return c}function La(a){var b=Ha(a)+1,c=Ca(b);Ga(a,x,c,b);return c}function Ma(a,b,c){for(var d=0;d>0]=a.charCodeAt(d);c||(x[b>>0]=0)}var Na,x,B,Oa,Pa,E,Qa,G,Ra; 21 | function Sa(a){Na=a;e.HEAP8=x=new Int8Array(a);e.HEAP16=Oa=new Int16Array(a);e.HEAP32=E=new Int32Array(a);e.HEAPU8=B=new Uint8Array(a);e.HEAPU16=Pa=new Uint16Array(a);e.HEAPU32=Qa=new Uint32Array(a);e.HEAPF32=G=new Float32Array(a);e.HEAPF64=Ra=new Float64Array(a)}var Ta=e.INITIAL_MEMORY||33554432;e.wasmMemory?ya=e.wasmMemory:ya=new WebAssembly.Memory({initial:Ta/65536,maximum:16384});ya&&(Na=ya.buffer);Ta=Na.byteLength;Sa(Na);var H,Ua=[],Wa=[],Xa=[],Ya=[],Za=[]; 22 | function $a(){var a=e.preRun.shift();Ua.unshift(a)}var ab=0,bb=null,cb=null;function db(){ab++;e.monitorRunDependencies&&e.monitorRunDependencies(ab)}function eb(){ab--;e.monitorRunDependencies&&e.monitorRunDependencies(ab);if(0==ab&&(null!==bb&&(clearInterval(bb),bb=null),cb)){var a=cb;cb=null;a()}}e.preloadedImages={};e.preloadedAudios={};function n(a){if(e.onAbort)e.onAbort(a);k(a);za=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");ca(a);throw a;} 23 | function fb(a){var b=gb;return String.prototype.startsWith?b.startsWith(a):0===b.indexOf(a)}function hb(){return fb("data:application/octet-stream;base64,")}var gb=chrome.runtime.getURL("dist/ffmpeg-core.wasm");if(!hb()){var ib=gb;gb=e.locateFile?e.locateFile(ib,l):l+ib}function jb(){try{if(xa)return new Uint8Array(xa);if(ta)return ta(gb);throw"both async and sync fetching of the wasm failed";}catch(a){n(a)}} 24 | function kb(){return xa||!na&&!pa||"function"!==typeof fetch||fb("file://")?Promise.resolve().then(jb):fetch(gb,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+gb+"'";return a.arrayBuffer()}).catch(function(){return jb()})}var I,J;function lb(a){for(;0>2]=a}function qb(a,b){if(0===a)a=Date.now();else if(1===a||4===a)a=nb();else return ob(28),-1;E[b>>2]=a/1E3|0;E[b+4>>2]=a%1E3*1E6|0;return 0} 26 | function rb(a,b){a=new Date(1E3*E[a>>2]);E[b>>2]=a.getUTCSeconds();E[b+4>>2]=a.getUTCMinutes();E[b+8>>2]=a.getUTCHours();E[b+12>>2]=a.getUTCDate();E[b+16>>2]=a.getUTCMonth();E[b+20>>2]=a.getUTCFullYear()-1900;E[b+24>>2]=a.getUTCDay();E[b+36>>2]=0;E[b+32>>2]=0;E[b+28>>2]=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0;rb.Hf||(rb.Hf=Ja("GMT"));E[b+40>>2]=rb.Hf;return b} 27 | function sb(){function a(h){return(h=h.toTimeString().match(/\(([A-Za-z ]+)\)$/))?h[1]:"GMT"}if(!tb){tb=!0;var b=(new Date).getFullYear(),c=new Date(b,0,1),d=new Date(b,6,1);b=c.getTimezoneOffset();var f=d.getTimezoneOffset(),g=Math.max(b,f);E[ub()>>2]=60*g;E[vb()>>2]=Number(b!=f);c=a(c);d=a(d);c=Ja(c);d=Ja(d);f>2]=c,E[wb()+4>>2]=d):(E[wb()>>2]=d,E[wb()+4>>2]=c)}}var tb; 28 | function xb(a,b){sb();a=new Date(1E3*E[a>>2]);E[b>>2]=a.getSeconds();E[b+4>>2]=a.getMinutes();E[b+8>>2]=a.getHours();E[b+12>>2]=a.getDate();E[b+16>>2]=a.getMonth();E[b+20>>2]=a.getFullYear()-1900;E[b+24>>2]=a.getDay();var c=new Date(a.getFullYear(),0,1);E[b+28>>2]=(a.getTime()-c.getTime())/864E5|0;E[b+36>>2]=-(60*a.getTimezoneOffset());var d=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();c=c.getTimezoneOffset();a=(d!=c&&a.getTimezoneOffset()==Math.min(c,d))|0;E[b+32>>2]=a;a=E[wb()+(a?4:0)>>2]; 29 | E[b+40>>2]=a;return b}function yb(a,b){for(var c=0,d=a.length-1;0<=d;d--){var f=a[d];"."===f?a.splice(d,1):".."===f?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a}function zb(a){var b="/"===a.charAt(0),c="/"===a.substr(-1);(a=yb(a.split("/").filter(function(d){return!!d}),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a} 30 | function Ab(a){var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1);a=b[0];b=b[1];if(!a&&!b)return".";b&&(b=b.substr(0,b.length-1));return a+b}function Bb(a){if("/"===a)return"/";a=zb(a);a=a.replace(/\/$/,"");var b=a.lastIndexOf("/");return-1===b?a:a.substr(b+1)}function Cb(a,b){return zb(a+"/"+b)} 31 | function Db(){if("object"===typeof crypto&&"function"===typeof crypto.getRandomValues){var a=new Uint8Array(1);return function(){crypto.getRandomValues(a);return a[0]}}if(qa)try{var b=require("crypto");return function(){return b.randomBytes(1)[0]}}catch(c){}return function(){n("randomDevice")}} 32 | function Eb(){for(var a="",b=!1,c=arguments.length-1;-1<=c&&!b;c--){b=0<=c?arguments[c]:K.cwd();if("string"!==typeof b)throw new TypeError("Arguments to path.resolve must be strings");if(!b)return"";a=b+"/"+a;b="/"===b.charAt(0)}a=yb(a.split("/").filter(function(d){return!!d}),!b).join("/");return(b?"/":"")+a||"."} 33 | function Fb(a,b){function c(h){for(var m=0;mr?[]:h.slice(m,r-m+1)}a=Eb(a).substr(1);b=Eb(b).substr(1);a=c(a.split("/"));b=c(b.split("/"));for(var d=Math.min(a.length,b.length),f=d,g=0;g=b||(b=Math.max(b,c*(1048576>c?2:1.125)>>>0),0!=c&&(b=Math.max(b,256)),c=a.Ud,a.Ud=new Uint8Array(b),0b)a.Ud.length=b;else for(;a.Ud.length=a.node.Zd)return 0;a=Math.min(a.node.Zd-f,d);if(8b)throw new K.Td(28);return b},Me:function(a,b,c){L.Qf(a.node,b+c);a.node.Zd=Math.max(a.node.Zd,b+c)},Ee:function(a,b,c,d,f,g){assert(0===b);if(!K.isFile(a.node.mode))throw new K.Td(43);a=a.node.Ud;if(g&2||a.buffer!==Na){if(0>>0)%K.qe.length},Xf:function(a){var b=K.sf(a.parent.id,a.name);a.Ae=K.qe[b];K.qe[b]=a},Yf:function(a){var b=K.sf(a.parent.id,a.name); 47 | if(K.qe[b]===a)K.qe[b]=a.Ae;else for(b=K.qe[b];b;){if(b.Ae===a){b.Ae=a.Ae;break}b=b.Ae}},pe:function(a,b){var c=K.Gg(a);if(c)throw new K.Td(c,a);for(c=K.qe[K.sf(a.id,b)];c;c=c.Ae){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return K.lookup(a,b)},createNode:function(a,b,c,d){a=new K.gg(a,b,c,d);K.Xf(a);return a},nf:function(a){K.Yf(a)},$e:function(a){return a===a.parent},ye:function(a){return!!a.Se},isFile:function(a){return 32768===(a&61440)},be:function(a){return 16384===(a&61440)},xe:function(a){return 40960=== 48 | (a&61440)},Oe:function(a){return 8192===(a&61440)},Cg:function(a){return 24576===(a&61440)},isFIFO:function(a){return 4096===(a&61440)},isSocket:function(a){return 49152===(a&49152)},yg:{r:0,rs:1052672,"r+":2,w:577,wx:705,xw:705,"w+":578,"wx+":706,"xw+":706,a:1089,ax:1217,xa:1217,"a+":1090,"ax+":1218,"xa+":1218},$f:function(a){var b=K.yg[a];if("undefined"===typeof b)throw Error("Unknown file open mode: "+a);return b},Rf:function(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b},ve:function(a, 49 | b){if(K.Zf)return 0;if(-1===b.indexOf("r")||a.mode&292){if(-1!==b.indexOf("w")&&!(a.mode&146)||-1!==b.indexOf("x")&&!(a.mode&73))return 2}else return 2;return 0},Gg:function(a){var b=K.ve(a,"x");return b?b:a.Vd.lookup?0:2},yf:function(a,b){try{return K.pe(a,b),20}catch(c){}return K.ve(a,"wx")},af:function(a,b,c){try{var d=K.pe(a,b)}catch(f){return f.Xd}if(a=K.ve(a,"wx"))return a;if(c){if(!K.be(d.mode))return 54;if(K.$e(d)||K.ue(d)===K.cwd())return 10}else if(K.be(d.mode))return 31;return 0},Hg:function(a, 50 | b){return a?K.xe(a.mode)?32:K.be(a.mode)&&("r"!==K.Rf(b)||b&512)?31:K.ve(a,K.Rf(b)):44},hg:4096,Jg:function(a,b){b=b||K.hg;for(a=a||0;a<=b;a++)if(!K.streams[a])return a;throw new K.Td(33);},ne:function(a){return K.streams[a]},Mf:function(a,b,c){K.jf||(K.jf=function(){},K.jf.prototype={object:{get:function(){return this.node},set:function(g){this.node=g}}});var d=new K.jf,f;for(f in a)d[f]=a[f];a=d;b=K.Jg(b,c);a.fd=b;return K.streams[b]=a},qg:function(a){K.streams[a]=null},pg:{open:function(a){a.Wd= 51 | K.zg(a.node.rdev).Wd;a.Wd.open&&a.Wd.open(a)},je:function(){throw new K.Td(70);}},wf:function(a){return a>>8},jh:function(a){return a&255},ze:function(a,b){return a<<8|b},Df:function(a,b){K.Of[a]={Wd:b}},zg:function(a){return K.Of[a]},Uf:function(a){var b=[];for(a=[a];a.length;){var c=a.pop();b.push(c);a.push.apply(a,c.Te)}return b},dg:function(a,b){function c(h){K.ef--;return b(h)}function d(h){if(h){if(!d.wg)return d.wg=!0,c(h)}else++g>=f.length&&c(null)}"function"===typeof a&&(b=a,a=!1);K.ef++; 52 | 1b)throw new K.Td(28);var c;"string"===typeof a?c=K.Yd(a,{le:!0}).node:c=a;if(!c.Vd.ee)throw new K.Td(63);if(K.be(c.mode))throw new K.Td(31);if(!K.isFile(c.mode))throw new K.Td(28);if(a=K.ve(c, 61 | "w"))throw new K.Td(a);c.Vd.ee(c,{size:b,timestamp:Date.now()})},dh:function(a,b){a=K.ne(a);if(!a)throw new K.Td(8);if(0===(a.flags&2097155))throw new K.Td(28);K.truncate(a.node,b)},qh:function(a,b,c){a=K.Yd(a,{le:!0}).node;a.Vd.ee(a,{timestamp:Math.max(b,c)})},open:function(a,b,c,d,f){if(""===a)throw new K.Td(44);b="string"===typeof b?K.$f(b):b;c=b&64?("undefined"===typeof c?438:c)&4095|32768:0;if("object"===typeof a)var g=a;else{a=zb(a);try{g=K.Yd(a,{le:!(b&131072)}).node}catch(m){}}var h=!1;if(b& 62 | 64)if(g){if(b&128)throw new K.Td(20);}else g=K.se(a,c,0),h=!0;if(!g)throw new K.Td(44);K.Oe(g.mode)&&(b&=-513);if(b&65536&&!K.be(g.mode))throw new K.Td(54);if(!h&&(c=K.Hg(g,b)))throw new K.Td(c);b&512&&K.truncate(g,0);b&=-131713;d=K.Mf({node:g,path:K.ue(g),flags:b,seekable:!0,position:0,Wd:g.Wd,Wg:[],error:!1},d,f);d.Wd.open&&d.Wd.open(d);!e.logReadFiles||b&1||(K.Af||(K.Af={}),a in K.Af||(K.Af[a]=1,k("FS.trackingDelegate error on read file: "+a)));try{K.de.onOpenFile&&(f=0,1!==(b&2097155)&&(f|=K.eg.bg.ig), 63 | 0!==(b&2097155)&&(f|=K.eg.bg.kg),K.de.onOpenFile(a,f))}catch(m){k("FS.trackingDelegate['onOpenFile']('"+a+"', flags) threw an exception: "+m.message)}return d},close:function(a){if(K.Pe(a))throw new K.Td(8);a.we&&(a.we=null);try{a.Wd.close&&a.Wd.close(a)}catch(b){throw b;}finally{K.qg(a.fd)}a.fd=null},Pe:function(a){return null===a.fd},je:function(a,b,c){if(K.Pe(a))throw new K.Td(8);if(!a.seekable||!a.Wd.je)throw new K.Td(70);if(0!=c&&1!=c&&2!=c)throw new K.Td(28);a.position=a.Wd.je(a,b,c);a.Wg=[]; 64 | return a.position},read:function(a,b,c,d,f){if(0>d||0>f)throw new K.Td(28);if(K.Pe(a))throw new K.Td(8);if(1===(a.flags&2097155))throw new K.Td(8);if(K.be(a.node.mode))throw new K.Td(31);if(!a.Wd.read)throw new K.Td(28);var g="undefined"!==typeof f;if(!g)f=a.position;else if(!a.seekable)throw new K.Td(70);b=a.Wd.read(a,b,c,d,f);g||(a.position+=b);return b},write:function(a,b,c,d,f,g){if(0>d||0>f)throw new K.Td(28);if(K.Pe(a))throw new K.Td(8);if(0===(a.flags&2097155))throw new K.Td(8);if(K.be(a.node.mode))throw new K.Td(31); 65 | if(!a.Wd.write)throw new K.Td(28);a.seekable&&a.flags&1024&&K.je(a,0,2);var h="undefined"!==typeof f;if(!h)f=a.position;else if(!a.seekable)throw new K.Td(70);b=a.Wd.write(a,b,c,d,f,g);h||(a.position+=b);try{if(a.path&&K.de.onWriteToFile)K.de.onWriteToFile(a.path)}catch(m){k("FS.trackingDelegate['onWriteToFile']('"+a.path+"') threw an exception: "+m.message)}return b},Me:function(a,b,c){if(K.Pe(a))throw new K.Td(8);if(0>b||0>=c)throw new K.Td(28);if(0===(a.flags&2097155))throw new K.Td(8);if(!K.isFile(a.node.mode)&& 66 | !K.be(a.node.mode))throw new K.Td(43);if(!a.Wd.Me)throw new K.Td(138);a.Wd.Me(a,b,c)},Ee:function(a,b,c,d,f,g){if(0!==(f&2)&&0===(g&2)&&2!==(a.flags&2097155))throw new K.Td(2);if(1===(a.flags&2097155))throw new K.Td(2);if(!a.Wd.Ee)throw new K.Td(43);return a.Wd.Ee(a,b,c,d,f,g)},Fe:function(a,b,c,d,f){return a&&a.Wd.Fe?a.Wd.Fe(a,b,c,d,f):0},lh:function(){return 0},De:function(a,b,c){if(!a.Wd.De)throw new K.Td(59);return a.Wd.De(a,b,c)},readFile:function(a,b){b=b||{};b.flags=b.flags||"r";b.encoding= 67 | b.encoding||"binary";if("utf8"!==b.encoding&&"binary"!==b.encoding)throw Error('Invalid encoding type "'+b.encoding+'"');var c,d=K.open(a,b.flags);a=K.stat(a).size;var f=new Uint8Array(a);K.read(d,f,0,a,0);"utf8"===b.encoding?c=Fa(f,0):"binary"===b.encoding&&(c=f);K.close(d);return c},writeFile:function(a,b,c){c=c||{};c.flags=c.flags||"w";a=K.open(a,c.flags,c.mode);if("string"===typeof b){var d=new Uint8Array(Ha(b)+1);b=Ga(b,d,0,d.length);K.write(a,d,0,b,void 0,c.og)}else if(ArrayBuffer.isView(b))K.write(a, 68 | b,0,b.byteLength,void 0,c.og);else throw Error("Unsupported data type");K.close(a)},cwd:function(){return K.Nf},chdir:function(a){a=K.Yd(a,{le:!0});if(null===a.node)throw new K.Td(44);if(!K.be(a.node.mode))throw new K.Td(54);var b=K.ve(a.node,"x");if(b)throw new K.Td(b);K.Nf=a.path},sg:function(){K.mkdir("/tmp");K.mkdir("/home");K.mkdir("/home/web_user")},rg:function(){K.mkdir("/dev");K.Df(K.ze(1,3),{read:function(){return 0},write:function(b,c,d,f){return f}});K.bf("/dev/null",K.ze(1,3));Hb(K.ze(5, 69 | 0),Kb);Hb(K.ze(6,0),Lb);K.bf("/dev/tty",K.ze(5,0));K.bf("/dev/tty1",K.ze(6,0));var a=Db();K.te("/dev","random",a);K.te("/dev","urandom",a);K.mkdir("/dev/shm");K.mkdir("/dev/shm/tmp")},ug:function(){K.mkdir("/proc");K.mkdir("/proc/self");K.mkdir("/proc/self/fd");K.ae({ae:function(){var a=K.createNode("/proc/self","fd",16895,73);a.Vd={lookup:function(b,c){var d=K.ne(+c);if(!d)throw new K.Td(8);b={parent:null,ae:{ag:"fake"},Vd:{readlink:function(){return d.path}}};return b.parent=b}};return a}},{},"/proc/self/fd")}, 70 | vg:function(){e.stdin?K.te("/dev","stdin",e.stdin):K.symlink("/dev/tty","/dev/stdin");e.stdout?K.te("/dev","stdout",null,e.stdout):K.symlink("/dev/tty","/dev/stdout");e.stderr?K.te("/dev","stderr",null,e.stderr):K.symlink("/dev/tty1","/dev/stderr");K.open("/dev/stdin","r");K.open("/dev/stdout","w");K.open("/dev/stderr","w")},Pf:function(){K.Td||(K.Td=function(a,b){this.node=b;this.Qg=function(c){this.Xd=c};this.Qg(a);this.message="FS error"},K.Td.prototype=Error(),K.Td.prototype.constructor=K.Td, 71 | [44].forEach(function(a){K.qf[a]=new K.Td(a);K.qf[a].stack=""}))},Rg:function(){K.Pf();K.qe=Array(4096);K.ae(L,{},"/");K.sg();K.rg();K.ug();K.xg={MEMFS:L}},Ne:function(a,b,c){K.Ne.tf=!0;K.Pf();e.stdin=a||e.stdin;e.stdout=b||e.stdout;e.stderr=c||e.stderr;K.vg()},quit:function(){K.Ne.tf=!1;var a=e._fflush;a&&a(0);for(a=0;athis.length-1||0>q)){var t=q%this.chunkSize;return this.Wf(q/this.chunkSize|0)[t]}};g.prototype.jg=function(q){this.Wf=q};g.prototype.Jf=function(){var q=new XMLHttpRequest;q.open("HEAD",c,!1);q.send(null);if(!(200<=q.status&&300>q.status||304===q.status))throw Error("Couldn't load "+c+". Status: "+q.status);var t=Number(q.getResponseHeader("Content-length")),v,C=(v=q.getResponseHeader("Accept-Ranges"))&&"bytes"===v;q=(v=q.getResponseHeader("Content-Encoding"))&&"gzip"===v;var p= 77 | 1048576;C||(p=t);var u=this;u.jg(function(w){var D=w*p,N=(w+1)*p-1;N=Math.min(N,t-1);if("undefined"===typeof u.Ce[w]){var Va=u.Ce;if(D>N)throw Error("invalid range ("+D+", "+N+") or no bytes requested!");if(N>t-1)throw Error("only "+t+" bytes available! programmer error!");var F=new XMLHttpRequest;F.open("GET",c,!1);t!==p&&F.setRequestHeader("Range","bytes="+D+"-"+N);"undefined"!=typeof Uint8Array&&(F.responseType="arraybuffer");F.overrideMimeType&&F.overrideMimeType("text/plain; charset=x-user-defined"); 78 | F.send(null);if(!(200<=F.status&&300>F.status||304===F.status))throw Error("Couldn't load "+c+". Status: "+F.status);D=void 0!==F.response?new Uint8Array(F.response||[]):Jb(F.responseText||"",!0);Va[w]=D}if("undefined"===typeof u.Ce[w])throw Error("doXHR failed!");return u.Ce[w]});if(q||!t)p=t=1,p=t=this.Wf(0).length,fa("LazyFiles on gzip forces download of the whole file when length is accessed");this.mg=t;this.lg=p;this.vf=!0};if("undefined"!==typeof XMLHttpRequest){if(!pa)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc"; 79 | var h=new g;Object.defineProperties(h,{length:{get:function(){this.vf||this.Jf();return this.mg}},chunkSize:{get:function(){this.vf||this.Jf();return this.lg}}});h={uf:!1,Ud:h}}else h={uf:!1,url:c};var m=K.tg(a,b,h,d,f);h.Ud?m.Ud=h.Ud:h.url&&(m.Ud=null,m.url=h.url);Object.defineProperties(m,{Zd:{get:function(){return this.Ud.length}}});var r={};Object.keys(m.Wd).forEach(function(q){var t=m.Wd[q];r[q]=function(){if(!K.Sf(m))throw new K.Td(29);return t.apply(null,arguments)}});r.read=function(q,t,v, 80 | C,p){if(!K.Sf(m))throw new K.Td(29);q=q.node.Ud;if(p>=q.length)return 0;C=Math.min(q.length-p,C);if(q.slice)for(var u=0;u>2]=d.dev;E[c+4>>2]=0;E[c+8>>2]=d.ino;E[c+12>>2]=d.mode;E[c+16>>2]=d.nlink;E[c+20>>2]=d.uid;E[c+24>>2]=d.gid;E[c+28>>2]=d.rdev;E[c+32>>2]=0;J=[d.size>>>0,(I=d.size,1<=+Math.abs(I)?0>>0:~~+Math.ceil((I-+(~~I>>>0))/4294967296)>>>0:0)];E[c+40>>2]=J[0];E[c+44>>2]=J[1];E[c+48>>2]=4096;E[c+52>>2]=d.blocks;E[c+56>>2]=d.atime.getTime()/1E3|0;E[c+60>> 85 | 2]=0;E[c+64>>2]=d.mtime.getTime()/1E3|0;E[c+68>>2]=0;E[c+72>>2]=d.ctime.getTime()/1E3|0;E[c+76>>2]=0;J=[d.ino>>>0,(I=d.ino,1<=+Math.abs(I)?0>>0:~~+Math.ceil((I-+(~~I>>>0))/4294967296)>>>0:0)];E[c+80>>2]=J[0];E[c+84>>2]=J[1];return 0}var Pb=void 0;function M(){Pb+=4;return E[Pb-4>>2]}function Qb(a){a=K.ne(a);if(!a)throw new K.Td(8);return a} 86 | var O={ae:function(){e.websocket=e.websocket&&"object"===typeof e.websocket?e.websocket:{};e.websocket.kf={};e.websocket.on=function(a,b){"function"===typeof b&&(this.kf[a]=b);return this};e.websocket.emit=function(a,b){"function"===typeof this.kf[a]&&this.kf[a].call(this,b)};return K.createNode(null,"/",16895,0)},createSocket:function(a,b,c){b&=-526337;c&&assert(1==b==(6==c));a={family:a,type:b,protocol:c,ce:null,error:null,Ue:{},pending:[],Ie:[],fe:O.ge};b=O.cf();c=K.createNode(O.root,b,49152,0); 87 | c.Je=a;b=K.Mf({path:b,node:c,flags:K.$f("r+"),seekable:!1,Wd:O.Wd});a.stream=b;return a},Ag:function(a){return(a=K.ne(a))&&K.isSocket(a.node.mode)?a.node.Je:null},Wd:{He:function(a){a=a.node.Je;return a.fe.He(a)},De:function(a,b,c){a=a.node.Je;return a.fe.De(a,b,c)},read:function(a,b,c,d){a=a.node.Je;d=a.fe.Cf(a,d);if(!d)return 0;b.set(d.buffer,c);return d.buffer.length},write:function(a,b,c,d){a=a.node.Je;return a.fe.Ef(a,b,c,d)},close:function(a){a=a.node.Je;a.fe.close(a)}},cf:function(){O.cf.current|| 88 | (O.cf.current=0);return"socket["+O.cf.current++ +"]"},ge:{Xe:function(a,b,c){if("object"===typeof b){var d=b;c=b=null}if(d)if(d._socket)b=d._socket.remoteAddress,c=d._socket.remotePort;else{c=/ws[s]?:\/\/([^:]+):(\d+)/.exec(d.url);if(!c)throw Error("WebSocket URL must be in the format ws(s)://address:port");b=c[1];c=parseInt(c[2],10)}else try{var f=e.websocket&&"object"===typeof e.websocket,g="ws:#".replace("#","//");f&&"string"===typeof e.websocket.url&&(g=e.websocket.url);if("ws://"===g||"wss://"=== 89 | g){var h=b.split("/");g=g+h[0]+":"+c+"/"+h.slice(1).join("/")}h="binary";f&&"string"===typeof e.websocket.subprotocol&&(h=e.websocket.subprotocol);var m=void 0;"null"!==h&&(h=h.replace(/^ +| +$/g,"").split(/ *, */),m=qa?{protocol:h.toString()}:h);f&&null===e.websocket.subprotocol&&(m=void 0);d=new (qa?require("ws"):WebSocket)(g,m);d.binaryType="arraybuffer"}catch(r){throw new K.Td(23);}b={$d:b,port:c,socket:d,Ye:[]};O.ge.If(a,b);O.ge.Bg(a,b);2===a.type&&"undefined"!==typeof a.Be&&b.Ye.push(new Uint8Array([255, 90 | 255,255,255,112,111,114,116,(a.Be&65280)>>8,a.Be&255]));return b},Ze:function(a,b,c){return a.Ue[b+":"+c]},If:function(a,b){a.Ue[b.$d+":"+b.port]=b},cg:function(a,b){delete a.Ue[b.$d+":"+b.port]},Bg:function(a,b){function c(){e.websocket.emit("open",a.stream.fd);try{for(var g=b.Ye.shift();g;)b.socket.send(g),g=b.Ye.shift()}catch(h){b.socket.close()}}function d(g){if("string"===typeof g)g=(new TextEncoder).encode(g);else{assert(void 0!==g.byteLength);if(0==g.byteLength)return;g=new Uint8Array(g)}var h= 91 | f;f=!1;h&&10===g.length&&255===g[0]&&255===g[1]&&255===g[2]&&255===g[3]&&112===g[4]&&111===g[5]&&114===g[6]&&116===g[7]?(g=g[8]<<8|g[9],O.ge.cg(a,b),b.port=g,O.ge.If(a,b)):(a.Ie.push({$d:b.$d,port:b.port,data:g}),e.websocket.emit("message",a.stream.fd))}var f=!0;qa?(b.socket.on("open",c),b.socket.on("message",function(g,h){h.Yg&&d((new Uint8Array(g)).buffer)}),b.socket.on("close",function(){e.websocket.emit("close",a.stream.fd)}),b.socket.on("error",function(){a.error=14;e.websocket.emit("error", 92 | [a.stream.fd,a.error,"ECONNREFUSED: Connection refused"])})):(b.socket.onopen=c,b.socket.onclose=function(){e.websocket.emit("close",a.stream.fd)},b.socket.onmessage=function(g){d(g.data)},b.socket.onerror=function(){a.error=14;e.websocket.emit("error",[a.stream.fd,a.error,"ECONNREFUSED: Connection refused"])})},He:function(a){if(1===a.type&&a.ce)return a.pending.length?65:0;var b=0,c=1===a.type?O.ge.Ze(a,a.ie,a.ke):null;if(a.Ie.length||!c||c&&c.socket.readyState===c.socket.CLOSING||c&&c.socket.readyState=== 93 | c.socket.CLOSED)b|=65;if(!c||c&&c.socket.readyState===c.socket.OPEN)b|=4;if(c&&c.socket.readyState===c.socket.CLOSING||c&&c.socket.readyState===c.socket.CLOSED)b|=16;return b},De:function(a,b,c){switch(b){case 21531:return b=0,a.Ie.length&&(b=a.Ie[0].data.length),E[c>>2]=b,0;default:return 28}},close:function(a){if(a.ce){try{a.ce.close()}catch(f){}a.ce=null}for(var b=Object.keys(a.Ue),c=0;cb;b++){var c=Number(a[b]);if(isNaN(c))return null;a[b]=c}return(a[0]|a[1]<<8|a[2]<<16|a[3]<<24)>>>0} 100 | function Sb(a){var b,c,d=[];if(!/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i.test(a))return null;if("::"===a)return[0,0,0,0,0,0,0,0];a=0===a.indexOf("::")?a.replace("::","Z:"):a.replace("::",":Z:");0b,"exceeded max address mappings of 65535"),b="172.29."+(b&255)+"."+(b&65280),Zb[b]=a,Yb[a]=b);return b}function ac(a){return Zb[a]?Zb[a]:null}function bc(a){return(a&255)+"."+(a>>8&255)+"."+(a>>16&255)+"."+(a>>24&255)} 103 | function cc(a){var b="",c,d=0,f=0,g=0,h=0;a=[a[0]&65535,a[0]>>16,a[1]&65535,a[1]>>16,a[2]&65535,a[2]>>16,a[3]&65535,a[3]>>16];var m=!0;for(c=0;5>c;c++)if(0!==a[c]){m=!1;break}if(m){c=bc(a[6]|a[7]<<16);if(-1===a[5])return"::ffff:"+c;if(0===a[5])return"0.0.0.0"===c&&(c=""),"0.0.0.1"===c&&(c="1"),"::"+c}for(c=0;8>c;c++)0===a[c]&&(1d&&(d=h,g=c-d+1);for(c=0;8>c;c++)1=g&&cc?":":"");return b} 104 | function ec(a,b){var c=Oa[a>>1],d=dc(Pa[a+2>>1]);switch(c){case 2:if(16!==b)return{Xd:28};a=E[a+4>>2];a=bc(a);break;case 10:if(28!==b)return{Xd:28};a=[E[a+8>>2],E[a+12>>2],E[a+16>>2],E[a+20>>2]];a=cc(a);break;default:return{Xd:5}}return{family:c,$d:a,port:d}} 105 | function fc(a,b,c,d){switch(b){case 2:c=Rb(c);Oa[a>>1]=b;E[a+4>>2]=c;Oa[a+2>>1]=Wb(d);break;case 10:c=Sb(c);E[a>>2]=b;E[a+8>>2]=c[0];E[a+12>>2]=c[1];E[a+16>>2]=c[2];E[a+20>>2]=c[3];Oa[a+2>>1]=Wb(d);E[a+4>>2]=0;E[a+24>>2]=0;break;default:return{Xd:5}}return{}}function hc(){void 0===hc.start&&(hc.start=Date.now());return 1E3*(Date.now()-hc.start)|0}var ic=1,jc=[],P=[],kc=[],lc=[],mc=[],R=[],T=[],nc=[],oc=[],pc={},qc={},rc=4;function U(a){sc||(sc=a)} 106 | function tc(a){for(var b=ic++,c=a.length;c>2]=h}}function wc(a,b,c,d,f,g,h,m){b=P[b];if(a=W[a](b,c))d=m&&Da(a.name,m,d),f&&(E[f>>2]=d),g&&(E[g>>2]=a.size),h&&(E[h>>2]=a.type)}function xc(a,b){Qa[a>>2]=b;Qa[a+4>>2]=(b-Qa[a>>2])/4294967296} 107 | function yc(a,b,c){if(b){var d=void 0;switch(a){case 36346:d=1;break;case 36344:0!=c&&1!=c&&U(1280);return;case 36345:d=0;break;case 34466:var f=W.getParameter(34467);d=f?f.length:0}if(void 0===d)switch(f=W.getParameter(a),typeof f){case "number":d=f;break;case "boolean":d=f?1:0;break;case "string":U(1280);return;case "object":if(null===f)switch(a){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 34068:d=0;break;default:U(1280);return}else{if(f instanceof Float32Array|| 108 | f instanceof Uint32Array||f instanceof Int32Array||f instanceof Array){for(a=0;a>2]=f[a];break;case 2:G[b+4*a>>2]=f[a];break;case 4:x[b+a>>0]=f[a]?1:0}return}try{d=f.name|0}catch(g){U(1280);k("GL_INVALID_ENUM in glGet"+c+"v: Unknown object returned from WebGL getParameter("+a+")! (error: "+g+")");return}}break;default:U(1280);k("GL_INVALID_ENUM in glGet"+c+"v: Native code calling glGet"+c+"v("+a+") and it returns "+f+" of type "+typeof f+"!");return}switch(c){case 1:xc(b, 109 | d);break;case 0:E[b>>2]=d;break;case 2:G[b>>2]=d;break;case 4:x[b>>0]=d?1:0}}else U(1281)}function zc(a){var b=Ha(a)+1,c=Ka(b);Da(a,c,b);return c}function Ac(a,b,c,d){if(c)if(a=W.getUniform(P[a],R[b]),"number"==typeof a||"boolean"==typeof a)switch(d){case 0:E[c>>2]=a;break;case 2:G[c>>2]=a}else for(b=0;b>2]=a[b];break;case 2:G[c+4*b>>2]=a[b]}else U(1281)} 110 | function Bc(a,b,c,d){if(c)if(a=W.getVertexAttrib(a,b),34975==b)E[c>>2]=a&&a.name;else if("number"==typeof a||"boolean"==typeof a)switch(d){case 0:E[c>>2]=a;break;case 2:G[c>>2]=a;break;case 5:E[c>>2]=Math.fround(a)}else for(b=0;b>2]=a[b];break;case 2:G[c+4*b>>2]=a[b];break;case 5:E[c+4*b>>2]=Math.fround(a[b])}else U(1281)} 111 | function Cc(a,b,c,d,f){a-=5120;a=1==a?B:4==a?E:6==a?G:5==a||28922==a?Qa:Pa;var g=31-Math.clz32(a.BYTES_PER_ELEMENT),h=rc;return a.subarray(f>>g,f+d*(c*({5:3,6:4,8:2,29502:3,29504:4}[b-6402]||1)*(1<>g)}var Dc=[],Ec=[],Fc={}; 112 | function Gc(){if(!Hc){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"===typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:la||"./this.program"},b;for(b in Fc)a[b]=Fc[b];var c=[];for(b in a)c.push(b+"="+a[b]);Hc=c}return Hc}var Hc,X={}; 113 | function Ic(a){Ic.buffer||(Ic.buffer=Ka(256),X["0"]="Success",X["-1"]="Invalid value for 'ai_flags' field",X["-2"]="NAME or SERVICE is unknown",X["-3"]="Temporary failure in name resolution",X["-4"]="Non-recoverable failure in name res",X["-6"]="'ai_family' not supported",X["-7"]="'ai_socktype' not supported",X["-8"]="SERVICE not supported for 'ai_socktype'",X["-10"]="Memory allocation failure",X["-11"]="System error returned in 'errno'",X["-12"]="Argument buffer overflow");var b="Unknown error"; 114 | a in X&&(255d-a.getDate())b-=d-a.getDate()+1,a.setDate(1),11>c?a.setMonth(c+1):(a.setMonth(0),a.setFullYear(a.getFullYear()+1));else{a.setDate(a.getDate()+b);break}}return a}function Rc(a,b,c,d){a||(a=this);this.parent=a;this.ae=a.ae;this.Se=null;this.id=K.Ig++;this.name=b;this.mode=c;this.Vd={};this.Wd={};this.rdev=d} 116 | Object.defineProperties(Rc.prototype,{read:{get:function(){return 365===(this.mode&365)},set:function(a){a?this.mode|=365:this.mode&=-366}},write:{get:function(){return 146===(this.mode&146)},set:function(a){a?this.mode|=146:this.mode&=-147}},Dg:{get:function(){return K.be(this.mode)}},uf:{get:function(){return K.Oe(this.mode)}}});K.gg=Rc;K.Rg();for(var Mb,W,Y=0;32>Y;++Y)uc.push(Array(Y));var Sc=new Float32Array(288);for(Y=0;288>Y;++Y)Dc[Y]=Sc.subarray(0,Y+1);var Tc=new Int32Array(288); 117 | for(Y=0;288>Y;++Y)Ec[Y]=Tc.subarray(0,Y+1);function Jb(a,b){var c=Array(Ha(a)+1);a=Ga(a,c,0,c.length);b&&(c.length=a);return c}Wa.push({Tf:function(){Uc()}}); 118 | var qd={c:function(a,b,c,d){n("Assertion failed: "+z(a)+", at: "+[b?z(b):"unknown filename",c,d?z(d):"unknown function"])},La:function(a,b){return qb(a,b)},M:function(a,b){Ya.unshift({Tf:a,We:b})},sa:function(a,b){return rb(a,b)},ra:function(a,b){return xb(a,b)},Ka:function(a,b,c,d){try{for(var f=0,g=b?E[b>>2]:0,h=b?E[b+4>>2]:0,m=c?E[c>>2]:0,r=c?E[c+4>>2]:0,q=d?E[d>>2]:0,t=d?E[d+4>>2]:0,v=0,C=0,p=0,u=0,w=0,D=0,N=(b?E[b>>2]:0)|(c?E[c>>2]:0)|(d?E[d>>2]:0),Va=(b?E[b+4>>2]:0)|(c?E[c+4>>2]:0)|(d?E[d+4>> 119 | 2]:0),F=0;FF?N&S:Va&S){var aa=K.ne(F);if(!aa)throw new K.Td(8);var ha=5;aa.Wd.He&&(ha=aa.Wd.He(aa));ha&1&&(32>F?g&S:h&S)&&(32>F?v|=S:C|=S,f++);ha&4&&(32>F?m&S:r&S)&&(32>F?p|=S:u|=S,f++);ha&2&&(32>F?q&S:t&S)&&(32>F?w|=S:D|=S,f++)}}b&&(E[b>>2]=v,E[b+4>>2]=C);c&&(E[c>>2]=p,E[c+4>>2]=u);d&&(E[d>>2]=w,E[d+4>>2]=D);return f}catch(oa){return"undefined"!==typeof K&&oa instanceof K.Td||n(oa),-oa.Xd}},Ba:function(a,b){try{a=z(a);if(b&-8)var c=-28;else{var d;(d=K.Yd(a,{le:!0}).node)? 120 | (a="",b&4&&(a+="r"),b&2&&(a+="w"),b&1&&(a+="x"),c=a&&K.ve(d,a)?-2:0):c=-44}return c}catch(f){return"undefined"!==typeof K&&f instanceof K.Td||n(f),-f.Xd}},o:function(a,b,c){Pb=c;try{var d=Qb(a);switch(b){case 0:var f=M();return 0>f?-28:K.open(d.path,d.flags,0,f).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return f=M(),d.flags|=f,0;case 12:return f=M(),Oa[f+0>>1]=2,0;case 13:case 14:return 0;case 16:case 8:return-28;case 9:return ob(28),-1;default:return-28}}catch(g){return"undefined"!== 121 | typeof K&&g instanceof K.Td||n(g),-g.Xd}},Ma:function(a,b){try{var c=Qb(a);return Ob(K.stat,c.path,b)}catch(d){return"undefined"!==typeof K&&d instanceof K.Td||n(d),-d.Xd}},Ia:function(a,b,c){try{var d=Qb(a);d.we||(d.we=K.readdir(d.path));a=0;for(var f=K.je(d,0,1),g=Math.floor(f/280);g>>0,(I=m,1<=+Math.abs(I)?0>>0:~~+Math.ceil((I-+(~~I>>>0))/4294967296)>>>0:0)];E[b+a>>2]=J[0];E[b+a+4>>2]=J[1];J=[280*(g+1)>>>0,(I=280*(g+1),1<=+Math.abs(I)?0>>0:~~+Math.ceil((I-+(~~I>>>0))/4294967296)>>>0:0)];E[b+a+8>>2]=J[0];E[b+a+12>>2]=J[1];Oa[b+a+16>>1]=280;x[b+a+18>>0]=r;Da(h,b+a+19,256);a+=280;g+=1}K.je(d,280*g,0);return a}catch(t){return"undefined"!==typeof K&&t instanceof K.Td||n(t),-t.Xd}},Ea:function(a,b){try{return Vc(b,0,136),E[b>>2]=1,E[b+4>> 123 | 2]=2,E[b+8>>2]=3,E[b+12>>2]=4,0}catch(c){return"undefined"!==typeof K&&c instanceof K.Td||n(c),-c.Xd}},G:function(a,b,c){Pb=c;try{var d=Qb(a);switch(b){case 21509:case 21505:return d.tty?0:-59;case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:return d.tty?0:-59;case 21519:if(!d.tty)return-59;var f=M();return E[f>>2]=0;case 21520:return d.tty?-28:-59;case 21531:return f=M(),K.De(d,b,f);case 21523:return d.tty?0:-59;case 21524:return d.tty?0:-59;default:n("bad ioctl syscall "+b)}}catch(g){return"undefined"!== 124 | typeof K&&g instanceof K.Td||n(g),-g.Xd}},Na:function(a,b){try{return a=z(a),Ob(K.lstat,a,b)}catch(c){return"undefined"!==typeof K&&c instanceof K.Td||n(c),-c.Xd}},Oa:function(a,b){try{return a=z(a),a=zb(a),"/"===a[a.length-1]&&(a=a.substr(0,a.length-1)),K.mkdir(a,b,0),0}catch(c){return"undefined"!==typeof K&&c instanceof K.Td||n(c),-c.Xd}},va:function(a,b,c,d,f,g){try{a:{g<<=12;var h=!1;if(0!==(d&16)&&0!==a%16384)var m=-28;else{if(0!==(d&32)){var r=Wc(16384,b);if(!r){m=-48;break a}Vc(r,0,b);h=!0}else{var q= 125 | K.ne(f);if(!q){m=-8;break a}var t=K.Ee(q,a,b,g,c,d);r=t.Og;h=t.lf}Nb[r]={Fg:r,Eg:b,lf:h,fd:f,Ng:c,flags:d,offset:g};m=r}}return m}catch(v){return"undefined"!==typeof K&&v instanceof K.Td||n(v),-v.Xd}},xa:function(){return 0},wa:function(a,b){try{if(-1===(a|0)||0===b)var c=-28;else{var d=Nb[a];if(d&&b===d.Eg){var f=K.ne(d.fd);if(d.Ng&2){var g=d.flags,h=d.offset,m=B.slice(a,a+b);K.Fe(f,m,h,b,g)}Nb[a]=null;d.lf&&Xc(d.Fg)}c=0}return c}catch(r){return"undefined"!==typeof K&&r instanceof K.Td||n(r),-r.Xd}}, 126 | Aa:function(){return-63},I:function(a,b,c){Pb=c;try{var d=z(a),f=M();return K.open(d,b,f).fd}catch(g){return"undefined"!==typeof K&&g instanceof K.Td||n(g),-g.Xd}},Ja:function(a,b){try{for(var c=0,d=0;d>1],h=32,m=K.ne(E[f>>2]);m&&(h=5,m.Wd.He&&(h=m.Wd.He(m)));(h&=g|24)&&c++;Oa[f+6>>1]=h}return c}catch(r){return"undefined"!==typeof K&&r instanceof K.Td||n(r),-r.Xd}},Ga:function(a,b,c,d){try{return d&&(E[d>>2]=-1,E[d+4>>2]=-1,E[d+8>>2]=-1,E[d+12>>2]=-1),0}catch(f){return"undefined"!== 127 | typeof K&&f instanceof K.Td||n(f),-f.Xd}},za:function(a,b,c){try{var d=Qb(a);return K.read(d,x,b,c)}catch(f){return"undefined"!==typeof K&&f instanceof K.Td||n(f),-f.Xd}},ta:function(a,b){try{return a=z(a),b=z(b),K.rename(a,b),0}catch(c){return"undefined"!==typeof K&&c instanceof K.Td||n(c),-c.Xd}},Da:function(a){try{return a=z(a),K.rmdir(a),0}catch(b){return"undefined"!==typeof K&&b instanceof K.Td||n(b),-b.Xd}},Fa:function(){return 0},n:function(a,b){try{Pb=b;b=function(){var V=O.Ag(M());if(!V)throw new K.Td(8); 128 | return V};var c=function(V){var Oc=M(),ed=M();if(V&&0===Oc)return null;V=ec(Oc,ed);if(V.Xd)throw new K.Td(V.Xd);V.$d=ac(V.$d)||V.$d;return V};switch(a){case 1:var d=M(),f=M(),g=M(),h=O.createSocket(d,f,g);return h.stream.fd;case 2:h=b();var m=c();h.fe.bind(h,m.$d,m.port);return 0;case 3:return h=b(),m=c(),h.fe.connect(h,m.$d,m.port),0;case 4:h=b();var r=M();h.fe.listen(h,r);return 0;case 5:h=b();var q=M();M();var t=h.fe.accept(h);q&&fc(q,t.family,$b(t.ie),t.ke);return t.stream.fd;case 6:return h= 129 | b(),q=M(),M(),fc(q,h.family,$b(h.df||"0.0.0.0"),h.Be),0;case 7:h=b();q=M();M();if(!h.ie)return-53;fc(q,h.family,$b(h.ie),h.ke);return 0;case 11:h=b();var v=M(),C=M();M();var p=c(!0);return p?h.fe.Ef(h,x,v,C,p.$d,p.port):K.write(h.stream,x,v,C);case 12:h=b();var u=M(),w=M();M();q=M();M();var D=h.fe.Cf(h,w);if(!D)return 0;q&&fc(q,h.family,$b(D.$d),D.port);B.set(D.buffer,u);return D.buffer.byteLength;case 14:return-50;case 15:h=b();var N=M(),Va=M(),F=M(),S=M();return 1===N&&4===Va?(E[F>>2]=h.error,E[S>> 130 | 2]=4,h.error=null,0):-50;case 16:h=b();v=M();M();var aa=E[v+8>>2],ha=E[v+12>>2],oa=E[v>>2],fd=E[v+4>>2];if(oa){m=ec(oa,fd);if(m.Xd)return-m.Xd;var gd=m.port;q=ac(m.$d)||m.$d}for(var Ia=0,Q=0;Q>2];var Pc=new Uint8Array(Ia);for(Q=C=0;Q>2],Ub=E[aa+(8*Q+4)>>2];for(u=0;u>0]}return h.fe.Ef(h,Pc,0,Ia,q,gd);case 17:h=b();v=M();M();aa=E[v+8>>2];ha=E[v+12>>2];for(Q=Ia=0;Q>2];D=h.fe.Cf(h,Ia);if(!D)return 0;(oa= 131 | E[v>>2])&&fc(oa,h.family,$b(D.$d),D.port);h=0;var Vb=D.buffer.byteLength;for(Q=0;0>2],Ub=E[aa+(8*Q+4)>>2])C=Math.min(Ub,Vb),u=D.buffer.subarray(h,h+C),B.set(u,Tb+h),h+=C,Vb-=C;return h;default:return-52}}catch(V){return"undefined"!==typeof K&&V instanceof K.Td||n(V),-V.Xd}},H:function(a,b){try{return a=z(a),Ob(K.stat,a,b)}catch(c){return"undefined"!==typeof K&&c instanceof K.Td||n(c),-c.Xd}},Ca:function(a){try{if(!a)return-21;var b={__size__:390,sysname:0,nodename:65, 132 | release:130,version:195,machine:260,domainname:325};Ma("Emscripten",a+b.sysname);Ma("emscripten",a+b.nodename);Ma("1.0",a+b.release);Ma("#1",a+b.version);Ma("x86-JS",a+b.machine);return 0}catch(c){return"undefined"!==typeof K&&c instanceof K.Td||n(c),-c.Xd}},ya:function(a){try{return a=z(a),K.unlink(a),0}catch(b){return"undefined"!==typeof K&&b instanceof K.Td||n(b),-b.Xd}},b:function(){n()},Ha:hc,Ra:qb,L:function(){n("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking")}, 133 | Sa:function(){n("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking")},V:function(a){W.activeTexture(a)},U:function(a,b){W.attachShader(P[a],T[b])},ja:function(a,b){W.me.beginQueryEXT(a,oc[b])},T:function(a,b,c){W.bindAttribLocation(P[a],b,z(c))},S:function(a,b){W.bindBuffer(a,jc[b])},R:function(a,b){W.bindFramebuffer(a,kc[b])},Q:function(a,b){W.bindRenderbuffer(a,lc[b])},P:function(a,b){W.bindTexture(a,mc[b])},ba:function(a){W.bindVertexArray(nc[a])}, 134 | O:function(a,b,c,d){W.blendColor(a,b,c,d)},wd:function(a){W.blendEquation(a)},vd:function(a,b){W.blendEquationSeparate(a,b)},ud:function(a,b){W.blendFunc(a,b)},td:function(a,b,c,d){W.blendFuncSeparate(a,b,c,d)},sd:function(a,b,c,d){W.bufferData(a,c?B.subarray(c,c+b):b,d)},rd:function(a,b,c,d){W.bufferSubData(a,b,B.subarray(d,d+c))},qd:function(a){return W.checkFramebufferStatus(a)},pd:function(a){W.clear(a)},od:function(a,b,c,d){W.clearColor(a,b,c,d)},nd:function(a){W.clearDepth(a)},md:function(a){W.clearStencil(a)}, 135 | ld:function(a,b,c,d){W.colorMask(!!a,!!b,!!c,!!d)},kd:function(a){W.compileShader(T[a])},jd:function(a,b,c,d,f,g,h,m){W.compressedTexImage2D(a,b,c,d,f,g,m?B.subarray(m,m+h):null)},id:function(a,b,c,d,f,g,h,m,r){W.compressedTexSubImage2D(a,b,c,d,f,g,h,r?B.subarray(r,r+m):null)},hd:function(a,b,c,d,f,g,h,m){W.copyTexImage2D(a,b,c,d,f,g,h,m)},gd:function(a,b,c,d,f,g,h,m){W.copyTexSubImage2D(a,b,c,d,f,g,h,m)},fd:function(){var a=tc(P),b=W.createProgram();b.name=a;P[a]=b;return a},ed:function(a){var b= 136 | tc(T);T[b]=W.createShader(a);return b},dd:function(a){W.cullFace(a)},cd:function(a,b){for(var c=0;c>2],f=jc[d];f&&(W.deleteBuffer(f),f.name=0,jc[d]=null)}},bd:function(a,b){for(var c=0;c>2],f=kc[d];f&&(W.deleteFramebuffer(f),f.name=0,kc[d]=null)}},ad:function(a){if(a){var b=P[a];b?(W.deleteProgram(b),b.name=0,P[a]=null,pc[a]=null):U(1281)}},la:function(a,b){for(var c=0;c>2],f=oc[d];f&&(W.me.deleteQueryEXT(f),oc[d]=null)}},$c:function(a, 137 | b){for(var c=0;c>2],f=lc[d];f&&(W.deleteRenderbuffer(f),f.name=0,lc[d]=null)}},_c:function(a){if(a){var b=T[a];b?(W.deleteShader(b),T[a]=null):U(1281)}},Zc:function(a,b){for(var c=0;c>2],f=mc[d];f&&(W.deleteTexture(f),f.name=0,mc[d]=null)}},aa:function(a,b){for(var c=0;c>2];W.deleteVertexArray(nc[d]);nc[d]=null}},Yc:function(a){W.depthFunc(a)},Xc:function(a){W.depthMask(!!a)},Wc:function(a,b){W.depthRange(a,b)},Vc:function(a,b){W.detachShader(P[a], 138 | T[b])},Uc:function(a){W.disable(a)},Tc:function(a){W.disableVertexAttribArray(a)},Sc:function(a,b,c){W.drawArrays(a,b,c)},Y:function(a,b,c,d){W.drawArraysInstanced(a,b,c,d)},Z:function(a,b){for(var c=uc[a],d=0;d>2];W.drawBuffers(c)},Rc:function(a,b,c,d){W.drawElements(a,b,c,d)},X:function(a,b,c,d,f){W.drawElementsInstanced(a,b,c,d,f)},Qc:function(a){W.enable(a)},Pc:function(a){W.enableVertexAttribArray(a)},ia:function(a){W.me.endQueryEXT(a)},Oc:function(){W.finish()},Nc:function(){W.flush()}, 139 | Mc:function(a,b,c,d){W.framebufferRenderbuffer(a,b,c,lc[d])},Lc:function(a,b,c,d,f){W.framebufferTexture2D(a,b,c,mc[d],f)},Kc:function(a){W.frontFace(a)},Jc:function(a,b){vc(a,b,"createBuffer",jc)},Hc:function(a,b){vc(a,b,"createFramebuffer",kc)},ma:function(a,b){for(var c=0;c>2]=0;break}var f=tc(oc);d.name=f;oc[f]=d;E[b+4*c>>2]=f}},Gc:function(a,b){vc(a,b,"createRenderbuffer",lc)},Fc:function(a,b){vc(a,b,"createTexture",mc)},$:function(a, 140 | b){vc(a,b,"createVertexArray",nc)},Ic:function(a){W.generateMipmap(a)},Ec:function(a,b,c,d,f,g,h){wc("getActiveAttrib",a,b,c,d,f,g,h)},Dc:function(a,b,c,d,f,g,h){wc("getActiveUniform",a,b,c,d,f,g,h)},Cc:function(a,b,c,d){a=W.getAttachedShaders(P[a]);var f=a.length;f>b&&(f=b);E[c>>2]=f;for(b=0;b>2]=T.indexOf(a[b])},Bc:function(a,b){return W.getAttribLocation(P[a],z(b))},Ac:function(a,b){yc(a,b,4)},zc:function(a,b,c){c?E[c>>2]=W.getBufferParameter(a,b):U(1281)},yc:function(){var a=W.getError()|| 141 | sc;sc=0;return a},xc:function(a,b){yc(a,b,2)},wc:function(a,b,c,d){a=W.getFramebufferAttachmentParameter(a,b,c);if(a instanceof WebGLRenderbuffer||a instanceof WebGLTexture)a=a.name|0;E[d>>2]=a},vc:function(a,b){yc(a,b,0)},tc:function(a,b,c,d){a=W.getProgramInfoLog(P[a]);null===a&&(a="(unknown error)");b=0>2]=b)},uc:function(a,b,c){if(c)if(a>=ic)U(1281);else{var d=pc[a];if(d)if(35716==b)a=W.getProgramInfoLog(P[a]),null===a&&(a="(unknown error)"),E[c>>2]=a.length+1;else if(35719== 142 | b)E[c>>2]=d.xf;else if(35722==b){if(-1==d.Qe){a=P[a];var f=W.getProgramParameter(a,35721);for(b=d.Qe=0;b>2]=d.Qe}else if(35381==b){if(-1==d.Re)for(a=P[a],f=W.getProgramParameter(a,35382),b=d.Re=0;b>2]=d.Re}else E[c>>2]=W.getProgramParameter(P[a],b);else U(1282)}else U(1281)},da:function(a,b,c){if(c){a=W.me.getQueryObjectEXT(oc[a],b);var d;"boolean"==typeof a? 143 | d=a?1:0:d=a;xc(c,d)}else U(1281)},fa:function(a,b,c){if(c){a=W.me.getQueryObjectEXT(oc[a],b);var d;"boolean"==typeof a?d=a?1:0:d=a;E[c>>2]=d}else U(1281)},ca:function(a,b,c){if(c){a=W.me.getQueryObjectEXT(oc[a],b);var d;"boolean"==typeof a?d=a?1:0:d=a;xc(c,d)}else U(1281)},ea:function(a,b,c){if(c){a=W.me.getQueryObjectEXT(oc[a],b);var d;"boolean"==typeof a?d=a?1:0:d=a;E[c>>2]=d}else U(1281)},ga:function(a,b,c){c?E[c>>2]=W.me.getQueryEXT(a,b):U(1281)},sc:function(a,b,c){c?E[c>>2]=W.getRenderbufferParameter(a, 144 | b):U(1281)},qc:function(a,b,c,d){a=W.getShaderInfoLog(T[a]);null===a&&(a="(unknown error)");b=0>2]=b)},pc:function(a,b,c,d){a=W.getShaderPrecisionFormat(a,b);E[c>>2]=a.rangeMin;E[c+4>>2]=a.rangeMax;E[d>>2]=a.precision},oc:function(a,b,c,d){if(a=W.getShaderSource(T[a]))b=0>2]=b)},rc:function(a,b,c){c?35716==b?(a=W.getShaderInfoLog(T[a]),null===a&&(a="(unknown error)"),E[c>>2]=a?a.length+1:0):35720==b?(a=W.getShaderSource(T[a]),E[c>>2]=a?a.length+ 145 | 1:0):E[c>>2]=W.getShaderParameter(T[a],b):U(1281)},nc:function(a){if(qc[a])return qc[a];switch(a){case 7939:var b=W.getSupportedExtensions()||[];b=b.concat(b.map(function(d){return"GL_"+d}));b=zc(b.join(" "));break;case 7936:case 7937:case 37445:case 37446:(b=W.getParameter(a))||U(1280);b=zc(b);break;case 7938:b=zc("OpenGL ES 2.0 ("+W.getParameter(7938)+")");break;case 35724:b=W.getParameter(35724);var c=b.match(/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/);null!==c&&(3==c[1].length&&(c[1]+="0"), 146 | b="OpenGL ES GLSL ES "+c[1]+" ("+b+")");b=zc(b);break;default:return U(1280),0}return qc[a]=b},mc:function(a,b,c){c?G[c>>2]=W.getTexParameter(a,b):U(1281)},lc:function(a,b,c){c?E[c>>2]=W.getTexParameter(a,b):U(1281)},ic:function(a,b){b=z(b);var c=0;if("]"==b[b.length-1]){var d=b.lastIndexOf("[");c="]"!=b[d+1]?parseInt(b.slice(d+1)):0;b=b.slice(0,d)}return(a=pc[a]&&pc[a].fg[b])&&0<=c&&c>2]=W.getVertexAttribOffset(a, 147 | b):U(1281)},hc:function(a,b,c){Bc(a,b,c,2)},gc:function(a,b,c){Bc(a,b,c,5)},ec:function(a,b){W.hint(a,b)},dc:function(a){return(a=jc[a])?W.isBuffer(a):0},cc:function(a){return W.isEnabled(a)},bc:function(a){return(a=kc[a])?W.isFramebuffer(a):0},ac:function(a){return(a=P[a])?W.isProgram(a):0},ka:function(a){return(a=oc[a])?W.me.isQueryEXT(a):0},$b:function(a){return(a=lc[a])?W.isRenderbuffer(a):0},_b:function(a){return(a=T[a])?W.isShader(a):0},Zb:function(a){return(a=mc[a])?W.isTexture(a):0},_:function(a){return(a= 148 | nc[a])?W.isVertexArray(a):0},Yb:function(a){W.lineWidth(a)},Xb:function(a){W.linkProgram(P[a]);var b=P[a];a=pc[a]={fg:{},xf:0,Qe:-1,Re:-1};for(var c=a.fg,d=W.getProgramParameter(b,35718),f=0;f>2]:-1;f+=z(E[c+4*g>>2],0>h?void 0:h)}W.shaderSource(T[a],f)},Nb:function(a, 150 | b,c){W.stencilFunc(a,b,c)},Mb:function(a,b,c,d){W.stencilFuncSeparate(a,b,c,d)},Lb:function(a){W.stencilMask(a)},Kb:function(a,b){W.stencilMaskSeparate(a,b)},Jb:function(a,b,c){W.stencilOp(a,b,c)},Ib:function(a,b,c,d){W.stencilOpSeparate(a,b,c,d)},Hb:function(a,b,c,d,f,g,h,m,r){W.texImage2D(a,b,c,d,f,g,h,m,r?Cc(m,h,d,f,r):null)},Gb:function(a,b,c){W.texParameterf(a,b,c)},Fb:function(a,b,c){W.texParameterf(a,b,G[c>>2])},Eb:function(a,b,c){W.texParameteri(a,b,c)},Db:function(a,b,c){W.texParameteri(a, 151 | b,E[c>>2])},Cb:function(a,b,c,d,f,g,h,m,r){var q=null;r&&(q=Cc(m,h,f,g,r));W.texSubImage2D(a,b,c,d,f,g,h,m,q)},Bb:function(a,b){W.uniform1f(R[a],b)},Ab:function(a,b,c){if(288>=b)for(var d=Dc[b-1],f=0;f>2];else d=G.subarray(c>>2,c+4*b>>2);W.uniform1fv(R[a],d)},zb:function(a,b){W.uniform1i(R[a],b)},yb:function(a,b,c){if(288>=b)for(var d=Ec[b-1],f=0;f>2];else d=E.subarray(c>>2,c+4*b>>2);W.uniform1iv(R[a],d)},xb:function(a,b,c){W.uniform2f(R[a],b,c)},wb:function(a, 152 | b,c){if(144>=b)for(var d=Dc[2*b-1],f=0;f<2*b;f+=2)d[f]=G[c+4*f>>2],d[f+1]=G[c+(4*f+4)>>2];else d=G.subarray(c>>2,c+8*b>>2);W.uniform2fv(R[a],d)},vb:function(a,b,c){W.uniform2i(R[a],b,c)},tb:function(a,b,c){if(144>=b)for(var d=Ec[2*b-1],f=0;f<2*b;f+=2)d[f]=E[c+4*f>>2],d[f+1]=E[c+(4*f+4)>>2];else d=E.subarray(c>>2,c+8*b>>2);W.uniform2iv(R[a],d)},sb:function(a,b,c,d){W.uniform3f(R[a],b,c,d)},rb:function(a,b,c){if(96>=b)for(var d=Dc[3*b-1],f=0;f<3*b;f+=3)d[f]=G[c+4*f>>2],d[f+1]=G[c+(4*f+4)>>2],d[f+2]= 153 | G[c+(4*f+8)>>2];else d=G.subarray(c>>2,c+12*b>>2);W.uniform3fv(R[a],d)},qb:function(a,b,c,d){W.uniform3i(R[a],b,c,d)},pb:function(a,b,c){if(96>=b)for(var d=Ec[3*b-1],f=0;f<3*b;f+=3)d[f]=E[c+4*f>>2],d[f+1]=E[c+(4*f+4)>>2],d[f+2]=E[c+(4*f+8)>>2];else d=E.subarray(c>>2,c+12*b>>2);W.uniform3iv(R[a],d)},ob:function(a,b,c,d,f){W.uniform4f(R[a],b,c,d,f)},nb:function(a,b,c){if(72>=b){var d=Dc[4*b-1],f=G;c>>=2;for(var g=0;g<4*b;g+=4){var h=c+g;d[g]=f[h];d[g+1]=f[h+1];d[g+2]=f[h+2];d[g+3]=f[h+3]}}else d=G.subarray(c>> 154 | 2,c+16*b>>2);W.uniform4fv(R[a],d)},mb:function(a,b,c,d,f){W.uniform4i(R[a],b,c,d,f)},lb:function(a,b,c){if(72>=b)for(var d=Ec[4*b-1],f=0;f<4*b;f+=4)d[f]=E[c+4*f>>2],d[f+1]=E[c+(4*f+4)>>2],d[f+2]=E[c+(4*f+8)>>2],d[f+3]=E[c+(4*f+12)>>2];else d=E.subarray(c>>2,c+16*b>>2);W.uniform4iv(R[a],d)},kb:function(a,b,c,d){if(72>=b)for(var f=Dc[4*b-1],g=0;g<4*b;g+=4)f[g]=G[d+4*g>>2],f[g+1]=G[d+(4*g+4)>>2],f[g+2]=G[d+(4*g+8)>>2],f[g+3]=G[d+(4*g+12)>>2];else f=G.subarray(d>>2,d+16*b>>2);W.uniformMatrix2fv(R[a], 155 | !!c,f)},ib:function(a,b,c,d){if(32>=b)for(var f=Dc[9*b-1],g=0;g<9*b;g+=9)f[g]=G[d+4*g>>2],f[g+1]=G[d+(4*g+4)>>2],f[g+2]=G[d+(4*g+8)>>2],f[g+3]=G[d+(4*g+12)>>2],f[g+4]=G[d+(4*g+16)>>2],f[g+5]=G[d+(4*g+20)>>2],f[g+6]=G[d+(4*g+24)>>2],f[g+7]=G[d+(4*g+28)>>2],f[g+8]=G[d+(4*g+32)>>2];else f=G.subarray(d>>2,d+36*b>>2);W.uniformMatrix3fv(R[a],!!c,f)},hb:function(a,b,c,d){if(18>=b){var f=Dc[16*b-1],g=G;d>>=2;for(var h=0;h<16*b;h+=16){var m=d+h;f[h]=g[m];f[h+1]=g[m+1];f[h+2]=g[m+2];f[h+3]=g[m+3];f[h+4]=g[m+ 156 | 4];f[h+5]=g[m+5];f[h+6]=g[m+6];f[h+7]=g[m+7];f[h+8]=g[m+8];f[h+9]=g[m+9];f[h+10]=g[m+10];f[h+11]=g[m+11];f[h+12]=g[m+12];f[h+13]=g[m+13];f[h+14]=g[m+14];f[h+15]=g[m+15]}}else f=G.subarray(d>>2,d+64*b>>2);W.uniformMatrix4fv(R[a],!!c,f)},gb:function(a){W.useProgram(P[a])},fb:function(a){W.validateProgram(P[a])},eb:function(a,b){W.vertexAttrib1f(a,b)},db:function(a,b){W.vertexAttrib1f(a,G[b>>2])},cb:function(a,b,c){W.vertexAttrib2f(a,b,c)},bb:function(a,b){W.vertexAttrib2f(a,G[b>>2],G[b+4>>2])},ab:function(a, 157 | b,c,d){W.vertexAttrib3f(a,b,c,d)},$a:function(a,b){W.vertexAttrib3f(a,G[b>>2],G[b+4>>2],G[b+8>>2])},_a:function(a,b,c,d,f){W.vertexAttrib4f(a,b,c,d,f)},Za:function(a,b){W.vertexAttrib4f(a,G[b>>2],G[b+4>>2],G[b+8>>2],G[b+12>>2])},W:function(a,b){W.vertexAttribDivisor(a,b)},Ya:function(a,b,c,d,f,g){W.vertexAttribPointer(a,b,c,!!d,f,g)},Xa:function(a,b,c,d){W.viewport(a,b,c,d)},f:function(a,b){Z(a,b||1);throw"longjmp";},na:function(a,b,c){B.copyWithin(a,b,b+c)},oa:function(a){a>>>=0;var b=B.length;if(1073741824< 158 | a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0>>16);Sa(ya.buffer);var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},pa:function(a,b){var c=0;Gc().forEach(function(d,f){var g=b+c;E[a+4*f>>2]=g;Ma(d,g);c+=d.length+1});return 0},qa:function(a,b){var c=Gc();E[a>>2]=c.length;var d=0;c.forEach(function(f){d+=f.length+1});E[b>>2]=d;return 0},v:function(a){ea(a)}, 159 | x:function(a){try{var b=Qb(a);K.close(b);return 0}catch(c){return"undefined"!==typeof K&&c instanceof K.Td||n(c),c.Xd}},F:function(a,b){try{var c=Qb(a);x[b>>0]=c.tty?2:K.be(c.mode)?3:K.xe(c.mode)?7:4;return 0}catch(d){return"undefined"!==typeof K&&d instanceof K.Td||n(d),d.Xd}},ua:function(a,b,c,d){try{a:{for(var f=Qb(a),g=a=0;g>2],m=K.read(f,x,E[b+8*g>>2],h,void 0);if(0>m){var r=-1;break a}a+=m;if(m>2]=r;return 0}catch(q){return"undefined"!==typeof K&&q instanceof 160 | K.Td||n(q),q.Xd}},Ta:function(a,b,c,d,f){try{var g=Qb(a);a=4294967296*c+(b>>>0);if(-9007199254740992>=a||9007199254740992<=a)return-61;K.je(g,a,d);J=[g.position>>>0,(I=g.position,1<=+Math.abs(I)?0>>0:~~+Math.ceil((I-+(~~I>>>0))/4294967296)>>>0:0)];E[f>>2]=J[0];E[f+4>>2]=J[1];g.we&&0===a&&0===d&&(g.we=null);return 0}catch(h){return"undefined"!==typeof K&&h instanceof K.Td||n(h),h.Xd}},A:function(a,b,c,d){try{a:{for(var f=Qb(a),g=a=0;g>2],E[b+(8*g+4)>>2],void 0);if(0>h){var m=-1;break a}a+=h}m=a}E[d>>2]=m;return 0}catch(r){return"undefined"!==typeof K&&r instanceof K.Td||n(r),r.Xd}},u:Ic,d:function(){return wa|0},r:function(a,b,c,d){function f(v,C,p,u,w,D){var N=10===v?28:16;w=10===v?cc(w):bc(w);N=Ka(N);w=fc(N,v,w,D);assert(!w.Xd);w=Ka(32);E[w+4>>2]=v;E[w+8>>2]=C;E[w+12>>2]=p;E[w+24>>2]=u;E[w+20>>2]=N;E[w+16>>2]=10===v?28:16;E[w+28>>2]=0;return w}var g=0,h=0,m=0,r=0,q=0,t=0;c&&(m=E[c>>2],r=E[c+4>>2],q=E[c+8>> 162 | 2],t=E[c+12>>2]);q&&!t&&(t=2===q?17:6);!q&&t&&(q=17===t?2:1);0===t&&(t=6);0===q&&(q=1);if(!a&&!b)return-2;if(m&-1088||0!==c&&E[c>>2]&2&&!a)return-1;if(m&32)return-2;if(0!==q&&1!==q&&2!==q)return-7;if(0!==r&&2!==r&&10!==r)return-6;if(b&&(b=z(b),h=parseInt(b,10),isNaN(h)))return m&1024?-2:-8;if(!a)return 0===r&&(r=2),0===(m&1)&&(2===r?g=Yc(2130706433):g=[0,0,0,1]),a=f(r,q,t,null,g,h),E[d>>2]=a,0;a=z(a);g=Rb(a);if(null!==g)if(0===r||2===r)r=2;else if(10===r&&m&8)g=[0,0,Yc(65535),g],r=10;else return-2; 163 | else if(g=Sb(a),null!==g)if(0===r||10===r)r=10;else return-2;if(null!=g)return a=f(r,q,t,a,g,h),E[d>>2]=a,0;if(m&4)return-2;a=$b(a);g=Rb(a);0===r?r=2:10===r&&(g=[0,0,Yc(65535),g]);a=f(r,q,t,null,g,h);E[d>>2]=a;return 0},q:function(a,b,c,d,f,g,h){b=ec(a,b);if(b.Xd)return-6;a=b.port;var m=b.$d;b=!1;if(c&&d){var r;if(h&1||!(r=ac(m))){if(h&8)return-2}else m=r;c=Da(m,c,d);c+1>=d&&(b=!0)}f&&g&&(c=Da(""+a,f,g),c+1>=g&&(b=!0));return b?-12:0},i:function(a){var b=Date.now();E[a>>2]=b/1E3|0;E[a+4>>2]=b%1E3* 164 | 1E3|0;return 0},l:rb,ub:Zc,jb:$c,g:ad,y:bd,D:cd,J:dd,C:hd,Va:id,Ua:jd,p:kd,t:ld,h:md,Qa:nd,K:od,Wa:pd,k:xb,a:ya,E:function(a){sb();var b=new Date(E[a+20>>2]+1900,E[a+16>>2],E[a+12>>2],E[a+8>>2],E[a+4>>2],E[a>>2],0),c=E[a+32>>2],d=b.getTimezoneOffset(),f=new Date(b.getFullYear(),0,1),g=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),h=f.getTimezoneOffset(),m=Math.min(h,g);0>c?E[a+32>>2]=Number(g!=h&&m==d):0>2]=b.getDay(); 165 | E[a+28>>2]=(b.getTime()-f.getTime())/864E5|0;return b.getTime()/1E3|0},Pa:function(a,b){if(0===a)return ob(28),-1;var c=E[a>>2];a=E[a+4>>2];if(0>a||999999999c)return ob(28),-1;0!==b&&(E[b>>2]=0,E[b+4>>2]=0);return Jc(1E6*c+a/1E3)},B:function(){return 6},N:function(){},e:function(a){wa=a|0},w:function(){return 0},j:function(a,b,c,d){function f(p,u,w){for(p="number"===typeof p?p.toString():p||"";p.length 166 | N?-1:0=h(w,p)?0>=h(u,p)?p.getFullYear()+1:p.getFullYear():p.getFullYear()-1}var q=E[d+40>>2];d={Ug:E[d>>2],Tg:E[d+4>>2],ff:E[d+8>>2],Ve:E[d+12>>2],Ke:E[d+16>>2],he:E[d+20>>2],gf:E[d+24>>2],hf:E[d+28>>2],oh:E[d+32>>2],Sg:E[d+36>>2],Vg:q?z(q):""};c=z(c);q={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c", 168 | "%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var t in q)c=c.replace(new RegExp(t,"g"),q[t]);var v="Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),C="January February March April May June July August September October November December".split(" ");q={"%a":function(p){return v[p.gf].substring(0,3)},"%A":function(p){return v[p.gf]}, 169 | "%b":function(p){return C[p.Ke].substring(0,3)},"%B":function(p){return C[p.Ke]},"%C":function(p){return g((p.he+1900)/100|0,2)},"%d":function(p){return g(p.Ve,2)},"%e":function(p){return f(p.Ve,2," ")},"%g":function(p){return r(p).toString().substring(2)},"%G":function(p){return r(p)},"%H":function(p){return g(p.ff,2)},"%I":function(p){p=p.ff;0==p?p=12:12p.ff?"AM":"PM"},"%S":function(p){return g(p.Ug,2)},"%t":function(){return"\t"},"%u":function(p){return p.gf||7},"%U":function(p){var u=new Date(p.he+1900,0,1),w=0===u.getDay()?u:Qc(u,7-u.getDay());p=new Date(p.he+1900,p.Ke,p.Ve);return 0>h(w,p)?g(Math.ceil((31-w.getDate()+(Lc(Kc(p.getFullYear())?Mc:Nc,p.getMonth()-1)-31)+p.getDate())/7),2):0===h(w,u)?"01":"00"},"%V":function(p){var u=new Date(p.he+1901,0,4),w=m(new Date(p.he+1900, 171 | 0,4));u=m(u);var D=Qc(new Date(p.he+1900,0,1),p.hf);return 0>h(D,w)?"53":0>=h(u,D)?"01":g(Math.ceil((w.getFullYear()h(w,p)?g(Math.ceil((31-w.getDate()+(Lc(Kc(p.getFullYear())?Mc:Nc,p.getMonth()-1)-31)+p.getDate())/7),2):0===h(w,u)?"01":"00"},"%y":function(p){return(p.he+1900).toString().substring(2)}, 172 | "%Y":function(p){return p.he+1900},"%z":function(p){p=p.Sg;var u=0<=p;p=Math.abs(p)/60;return(u?"+":"-")+String("0000"+(p/60*100+p%60)).slice(-4)},"%Z":function(p){return p.Vg},"%%":function(){return"%"}};for(t in q)0<=c.indexOf(t)&&(c=c.replace(new RegExp(t,"g"),q[t](d)));t=Jb(c,!1);if(t.length>b)return 0;x.set(t,a);return t.length-1},s:function(a){switch(a){case 30:return 16384;case 85:return 65536;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809; 173 | case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32; 174 | case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1E3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:return"object"===typeof navigator?navigator.hardwareConcurrency||1:1}ob(28);return-1}, 175 | m:function(a){var b=Date.now()/1E3|0;a&&(E[a>>2]=b);return b},z:Jc}; 176 | (function(){function a(f){e.asm=f.exports;H=e.asm.xd;eb()}function b(f){a(f.instance)}function c(f){return kb().then(function(g){return WebAssembly.instantiate(g,d)}).then(f,function(g){k("failed to asynchronously prepare wasm: "+g);n(g)})}var d={a:qd};db();if(e.instantiateWasm)try{return e.instantiateWasm(d,a)}catch(f){return k("Module.instantiateWasm callback failed with error: "+f),!1}(function(){return xa||"function"!==typeof WebAssembly.instantiateStreaming||hb()||fb("file://")||"function"!== 177 | typeof fetch?c(b):fetch(gb,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,d).then(b,function(g){k("wasm streaming compile failed: "+g);k("falling back to ArrayBuffer instantiation");return c(b)})})})().catch(ca);return{}})(); 178 | var Uc=e.___wasm_call_ctors=function(){return(Uc=e.___wasm_call_ctors=e.asm.yd).apply(null,arguments)},Xc=e._free=function(){return(Xc=e._free=e.asm.zd).apply(null,arguments)},Vc=e._memset=function(){return(Vc=e._memset=e.asm.Ad).apply(null,arguments)},Ka=e._malloc=function(){return(Ka=e._malloc=e.asm.Bd).apply(null,arguments)},pb=e.___errno_location=function(){return(pb=e.___errno_location=e.asm.Cd).apply(null,arguments)};e._fflush=function(){return(e._fflush=e.asm.Dd).apply(null,arguments)}; 179 | var Wc=e._memalign=function(){return(Wc=e._memalign=e.asm.Ed).apply(null,arguments)},dc=e._ntohs=function(){return(dc=e._ntohs=e.asm.Fd).apply(null,arguments)},Wb=e._htons=function(){return(Wb=e._htons=e.asm.Gd).apply(null,arguments)};e._main=function(){return(e._main=e.asm.Hd).apply(null,arguments)}; 180 | var Yc=e._htonl=function(){return(Yc=e._htonl=e.asm.Id).apply(null,arguments)},wb=e.__get_tzname=function(){return(wb=e.__get_tzname=e.asm.Jd).apply(null,arguments)},vb=e.__get_daylight=function(){return(vb=e.__get_daylight=e.asm.Kd).apply(null,arguments)},ub=e.__get_timezone=function(){return(ub=e.__get_timezone=e.asm.Ld).apply(null,arguments)},y=e.stackSave=function(){return(y=e.stackSave=e.asm.Md).apply(null,arguments)},A=e.stackRestore=function(){return(A=e.stackRestore=e.asm.Nd).apply(null,arguments)}, 181 | Ca=e.stackAlloc=function(){return(Ca=e.stackAlloc=e.asm.Od).apply(null,arguments)},Z=e._setThrew=function(){return(Z=e._setThrew=e.asm.Pd).apply(null,arguments)},rd=e.dynCall_vijjjid=function(){return(rd=e.dynCall_vijjjid=e.asm.Qd).apply(null,arguments)},sd=e.dynCall_iiiijj=function(){return(sd=e.dynCall_iiiijj=e.asm.Rd).apply(null,arguments)},td=e.dynCall_iij=function(){return(td=e.dynCall_iij=e.asm.Sd).apply(null,arguments)};e._ff_h264_cabac_tables=2113942; 182 | function ad(a,b,c){var d=y();try{return H.get(a)(b,c)}catch(f){A(d);if(f!==f+0&&"longjmp"!==f)throw f;Z(1,0)}}function kd(a,b){var c=y();try{H.get(a)(b)}catch(d){A(c);if(d!==d+0&&"longjmp"!==d)throw d;Z(1,0)}}function md(a,b,c,d,f){var g=y();try{H.get(a)(b,c,d,f)}catch(h){A(g);if(h!==h+0&&"longjmp"!==h)throw h;Z(1,0)}}function ld(a,b,c){var d=y();try{H.get(a)(b,c)}catch(f){A(d);if(f!==f+0&&"longjmp"!==f)throw f;Z(1,0)}} 183 | function cd(a,b,c,d,f){var g=y();try{return H.get(a)(b,c,d,f)}catch(h){A(g);if(h!==h+0&&"longjmp"!==h)throw h;Z(1,0)}}function hd(a,b,c,d,f,g,h,m,r){var q=y();try{return H.get(a)(b,c,d,f,g,h,m,r)}catch(t){A(q);if(t!==t+0&&"longjmp"!==t)throw t;Z(1,0)}}function Zc(a){var b=y();try{return H.get(a)()}catch(c){A(b);if(c!==c+0&&"longjmp"!==c)throw c;Z(1,0)}}function $c(a,b){var c=y();try{return H.get(a)(b)}catch(d){A(c);if(d!==d+0&&"longjmp"!==d)throw d;Z(1,0)}} 184 | function bd(a,b,c,d){var f=y();try{return H.get(a)(b,c,d)}catch(g){A(f);if(g!==g+0&&"longjmp"!==g)throw g;Z(1,0)}}function od(a,b,c,d,f,g,h,m,r){var q=y();try{H.get(a)(b,c,d,f,g,h,m,r)}catch(t){A(q);if(t!==t+0&&"longjmp"!==t)throw t;Z(1,0)}}function dd(a,b,c,d,f,g){var h=y();try{return H.get(a)(b,c,d,f,g)}catch(m){A(h);if(m!==m+0&&"longjmp"!==m)throw m;Z(1,0)}}function nd(a,b,c,d,f,g,h){var m=y();try{H.get(a)(b,c,d,f,g,h)}catch(r){A(m);if(r!==r+0&&"longjmp"!==r)throw r;Z(1,0)}} 185 | function pd(a,b,c,d,f,g,h,m,r,q){var t=y();try{rd(a,b,c,d,f,g,h,m,r,q)}catch(v){A(t);if(v!==v+0&&"longjmp"!==v)throw v;Z(1,0)}}function id(a,b,c,d,f,g,h,m){var r=y();try{return sd(a,b,c,d,f,g,h,m)}catch(q){A(r);if(q!==q+0&&"longjmp"!==q)throw q;Z(1,0)}}function jd(a,b,c,d){var f=y();try{return td(a,b,c,d)}catch(g){A(f);if(g!==g+0&&"longjmp"!==g)throw g;Z(1,0)}}e.ccall=Ba; 186 | e.cwrap=function(a,b,c,d){c=c||[];var f=c.every(function(g){return"number"===g});return"string"!==b&&f&&!d?Aa(a):function(){return Ba(a,b,c,arguments,d)}}; 187 | e.setValue=function(a,b,c){c=c||"i8";"*"===c.charAt(c.length-1)&&(c="i32");switch(c){case "i1":x[a>>0]=b;break;case "i8":x[a>>0]=b;break;case "i16":Oa[a>>1]=b;break;case "i32":E[a>>2]=b;break;case "i64":J=[b>>>0,(I=b,1<=+Math.abs(I)?0>>0:~~+Math.ceil((I-+(~~I>>>0))/4294967296)>>>0:0)];E[a>>2]=J[0];E[a+4>>2]=J[1];break;case "float":G[a>>2]=b;break;case "double":Ra[a>>3]=b;break;default:n("invalid type for setValue: "+c)}};e.UTF8ToString=z; 188 | e.stringToUTF8=Da;e.lengthBytesUTF8=Ha;e.writeAsciiToMemory=Ma;e.FS=K;var ud;function da(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}cb=function vd(){ud||wd();ud||(cb=vd)}; 189 | function wd(a){function b(){if(!ud&&(ud=!0,e.calledRun=!0,!za)){e.noFSInit||K.Ne.tf||K.Ne();O.root=K.ae(O,{},null);lb(Wa);K.Zf=!1;lb(Xa);ba(e);if(e.onRuntimeInitialized)e.onRuntimeInitialized();if(xd){var c=a,d=e._main;c=c||[];var f=c.length+1,g=Ca(4*(f+1));E[g>>2]=La(la);for(var h=1;h>2)+h]=La(c[h-1]);E[(g>>2)+f]=0;try{var m=d(f,g);ea(m,!0)}catch(r){r instanceof da||("unwind"==r?noExitRuntime=!0:((c=r)&&"object"===typeof r&&r.stack&&(c=[r,r.stack]),k("exception thrown: "+c),ma(1,r)))}finally{}}if(e.postRun)for("function"== 190 | typeof e.postRun&&(e.postRun=[e.postRun]);e.postRun.length;)c=e.postRun.shift(),Za.unshift(c);lb(Za)}}a=a||ka;if(!(0 { 8 | const argsPtr = Core._malloc(args.length * Uint32Array.BYTES_PER_ELEMENT); 9 | args.forEach((s, idx) => { 10 | const buf = Core._malloc(s.length + 1); 11 | Core.writeAsciiToMemory(s, buf); 12 | Core.setValue(argsPtr + Uint32Array.BYTES_PER_ELEMENT * idx, buf, "i32"); 13 | }); 14 | return [args.length, argsPtr]; 15 | }; 16 | 17 | // ffmpegの実行 18 | const ffmpeg = (Core, args) => { 19 | Core.ccall( 20 | "main", 21 | "number", 22 | ["number", "number"], 23 | parseArgs(Core, ["ffmpeg", "-nostdin", ...args]) 24 | ); //https://github.com/naari3/nico-downloader-ffmpeg/blob/main/src/background.ts 25 | }; 26 | 27 | //////////////////////////////////////////////////////////////// 28 | /** 29 | * m3u8を変換する 30 | * @param {Core} Core 31 | * @param {String} m3u8name 32 | * @param {NicoDownloaderClass} NicoDownloader 33 | * @param {NicovideoClass} Nicovideo 34 | * @param {String} mode 35 | */ 36 | //////////////////////////////////////////////////////////////// 37 | const runFFmpeg_m3u8 = async ( 38 | Core, 39 | m3u8name, 40 | NicoDownloader, 41 | Nicovideo, 42 | mode = "mp4"//デフォルトはmp4 43 | ) => { 44 | let resolve = null; 45 | 46 | //終了を待つためのPromise 47 | const waitEnd = new Promise((r) => { 48 | resolve = r; 49 | }); 50 | 51 | //終了時にresolve 52 | try { 53 | //日本語が入っているとタグが変になるのでエンコード 54 | //unescapeは非推奨だが見なかったことにする 55 | const title_str = unescape(encodeURIComponent(Nicovideo.video_title)); 56 | const timestamp_str = unescape( 57 | encodeURIComponent(Nicovideo.video_registeredAt) 58 | ); 59 | const username_str = unescape(encodeURIComponent(Nicovideo.video_owner)); 60 | const description_str = unescape( 61 | encodeURIComponent(Nicovideo.video_description) 62 | ); 63 | 64 | // ジャンルとシリーズは日本語が入っているとエラーになるのでエンコード 65 | //unescapeは非推奨だが見なかったことにする 66 | const genre_str = unescape(encodeURIComponent(Nicovideo.video_genre)); 67 | const series_str = unescape(encodeURIComponent(Nicovideo.video_series)); 68 | 69 | //拡張子を設定 70 | NicoDownloader.SetVideFormatByExtension(mode); 71 | 72 | // 出力ファイル名を設定 73 | NicoDownloader.FSOutputFileNameSet(Nicovideo); 74 | const outputFileName = NicoDownloader.FSOutputFileNameGet(); 75 | 76 | DebugPrint(`OutputFileName: ${outputFileName}`); 77 | 78 | //ffmpeg実行 79 | ffmpeg(Core, [ 80 | "-allowed_extensions", 81 | "ALL", 82 | "-i", 83 | m3u8name, 84 | "-metadata", 85 | `title=${title_str}`, // タイトル 86 | "-metadata", 87 | `show=${title_str}`, // タイトル 88 | "-metadata", 89 | `creation_time=${timestamp_str}`, // 登録日時 90 | "-metadata", 91 | `date=${timestamp_str}`, // 登録日時 92 | "-metadata", 93 | `artist=${username_str}`, // 投稿ユーザ 94 | "-metadata", 95 | `description=${description_str}`, // 説明 96 | "-metadata", 97 | `comment=${description_str}`, // 説明 98 | "-metadata", 99 | `genre=${genre_str}`, // ジャンル 100 | "-metadata", 101 | `publisher=nicovideo.jp`, // パブリッシャ 102 | "-metadata", 103 | `episode_id=${Nicovideo.video_sm}`, // 動画ID 104 | "-metadata", 105 | `album=${series_str}`, // シリーズ 106 | "-metadata", 107 | `album_artist=${username_str}`, // 投稿ユーザ 108 | ...(mode === "aac" 109 | ? ["-vn", "-c:a", "copy"] // aacモードで最初のオーディオストリームを選択 110 | : ["-c", "copy"]), // MP4モードでオーディオ・ビデオをコピー 111 | outputFileName, 112 | ]); 113 | DebugPrint(`ffmpeg called with args: ${ffmpegArgs.join(" ")}`); 114 | } catch (err) { 115 | //エラーが出たら 116 | DebugPrint("runFFmpeg:" + err); 117 | } 118 | 119 | //終了を待つ 120 | await waitEnd; 121 | 122 | //終了後 123 | DebugPrint("waitEnd"); 124 | }; 125 | 126 | /** 127 | * ファイルタイプからMIMEタイプを返す 128 | * @param {String} filetype ファイルタイプ 129 | * @returns {String} MIMEタイプ 130 | * @see https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types 131 | * @see https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types 132 | * @see https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types 133 | */ 134 | function FiletypeToMimetype(filetype) { 135 | switch (filetype) { 136 | case "mp4": 137 | return "video/mp4"; 138 | case "wav": 139 | return "audio/wav"; 140 | case "mp3": 141 | return "audio/mpeg"; 142 | case "webm": 143 | return "video/webm"; 144 | case "aac": 145 | return "audio/aac"; 146 | default: 147 | return "video/mp4"; 148 | } 149 | } 150 | 151 | //ここから追記 152 | /** 153 | * ダウンロードし変換する関数 154 | * @param {NicoDownloaderClass} NicoDownloader 155 | * @param {Array} m3u8s 156 | * @param {NicovideoClass} Nicovideo 157 | * @returns 158 | */ 159 | async function DownEncoder(NicoDownloader, m3u8s, Nicovideo) { 160 | NicoDownloader.SetVideoFormat(Nicovideo.video_name); //フォーマットをセット 161 | if (NicoDownloader.CheckVideoFormat() == false) return false; //フォーマットをチェック 162 | 163 | //ダウンロード前のチェック処理 164 | if (NicoDownloader.VideoDownloadingCheck()) { 165 | //ダウンロード中は終了 166 | return false; 167 | } else { 168 | NicoDownloader.VideoDownloadingSet(); //ダウンロード中フラグを立てる 169 | } 170 | 171 | NicoDownloader.DownloadFaultNumReset(); //ダウンロードエラー数をリセット 172 | 173 | NicoDownloader.DownloadPercentageReset(); //パーセンテージをリセット 174 | 175 | //https://github.com/naari3/nico-downloader-ffmpeg/blob/main/src/background.ts //偉大なる@_naari_氏による協力に感謝いたします 176 | let file = null; 177 | const core = await createFFmpegCore({ 178 | printErr: (e) => DebugPrint(`FFMPEG:${e}`), 179 | print: (e) => { 180 | DebugPrint(`FFMPEG: ${e}`); 181 | if (e.startsWith("FFMPEG_END")) { 182 | // FFMPEG_ENDで終了 183 | //終了時の処理 184 | NicoDownloader.ButtonTextWrite("変換終了"); 185 | DebugPrint("FFMPEG_END 変換終了"); 186 | if (last_save_sm !== Nicovideo.video_sm) { 187 | try { 188 | last_save_sm = Nicovideo.video_sm; 189 | //NicoDownloader.FSOutputFileNameSet(Nicovideo); 190 | 191 | file = core.FS.readFile(NicoDownloader.FSOutputFileNameGet()); 192 | console.log({ file }); 193 | 194 | //ファイルの保存処理 195 | DebugPrint("ファイルの保存処理"); 196 | //blob 197 | const blob = new Blob([file.buffer], { 198 | //MIMEタイプを設定 199 | type: FiletypeToMimetype(NicoDownloader.CheckVideoFormat()), 200 | }); 201 | DebugPrint("Blob作成完了"); 202 | 203 | //ディスクへの保存処理 204 | const a = document.createElement("a"); 205 | const fileName = Nicovideo.video_name; 206 | 207 | a.id = VideoData.Video_DLlink.a2; 208 | document.body.appendChild(a); 209 | 210 | const link = document.getElementById(VideoData.Video_DLlink.a2); 211 | link.href = URL.createObjectURL(blob); 212 | link.download = fileName; 213 | 214 | link.style.display = "none"; 215 | 216 | document.body.click(); 217 | 218 | core.FS.unlink(NicoDownloader.FSOutputFileNameGet()); 219 | NicoDownloader.ButtonTextWrite("まもなく保存完了"); 220 | } catch (e) { 221 | console.error("Error:FaildedToBlob\n", e); 222 | } 223 | } else { 224 | DebugPrint("Error:既に保存済み"); 225 | } 226 | } 227 | }, 228 | }); 229 | console.debug({ core }); 230 | 231 | //URLsを片っ端から処理 232 | //落としてファイルシステムにいれていく 233 | let promises = []; 234 | for (let i = 0; i < NicoDownloader.TSURLs.length; i++) { 235 | const promise = new Promise((resolve, reject) => { 236 | DownloadUint8Array(NicoDownloader.TSURLs[i], NicoDownloader).then( 237 | (byte) => { 238 | let filenumber = i + 1; 239 | 240 | let filename = NicoDownloader.TSFilenames[i]; 241 | core.FS.writeFile(filename, byte); 242 | DebugPrint("FSwrite:" + filename); 243 | 244 | //ダウンロードパーセンテージを計算 245 | const downpercentage = 246 | (100 * filenumber) / NicoDownloader.TSURLs.length; 247 | if (downpercentage > NicoDownloader.DownloadPercentageGet()) { 248 | NicoDownloader.DownloadPercentageSet(downpercentage); 249 | } 250 | 251 | //ダウンロード中のテキストを書き換え 252 | let text_dl = 253 | NicoDownloader.LangText("ダウンロード中") + 254 | "…… (" + 255 | NicoDownloader.DownloadPercentageGet().toFixed(1) + 256 | "%)"; 257 | 258 | //ダウンロードエラー数がある場合はエラー発生の●を表示 259 | if (NicoDownloader.DownloadFaultNumCheck() != 0) { 260 | text_dl += "●"; 261 | } 262 | 263 | //ボタンのテキストを書き換え 264 | NicoDownloader.ButtonTextWrite(text_dl); 265 | 266 | DebugPrint("180: " + core.FS.stat(filename)); 267 | 268 | //最後のファイルの場合はresolve 269 | resolve(filename); 270 | } 271 | ); 272 | }); 273 | 274 | promises.push(promise); 275 | 276 | if (i % 2 == 1) { 277 | await Promise.all(promises); 278 | } 279 | } 280 | 281 | //Transcodeする 282 | 283 | await Promise.all(promises).then(() => { 284 | //間違ってURLを読みに行くのでm3u8を3つ書き換える 285 | //m3u8末尾の3個 286 | const m3u8s_num = m3u8s.length / 2; 287 | for (let i = 0; i < m3u8s_num; i++) { 288 | DebugPrint( 289 | m3u8s[m3u8s_num + i] + " -> " + new TextEncoder().encode(m3u8s[i]) 290 | ); 291 | core.FS.writeFile( 292 | m3u8s[m3u8s_num + i], 293 | new TextEncoder().encode(m3u8s[i]) 294 | ); 295 | } 296 | 297 | const m3u8name = m3u8s[m3u8s.length - 1]; 298 | NicoDownloader.ButtonTextWrite("結合処理中"); 299 | 300 | Transcode(core, m3u8name, NicoDownloader, Nicovideo).then(() => { 301 | NicoDownloader.VideoDownloadingReset(); // ダウンロード中をリセット 302 | }); 303 | }); 304 | 305 | return true; 306 | } 307 | 308 | //////////////////////////////////////////////////////////////////////// 309 | /** 310 | * URLからダウンロードし、Blobを返す 311 | * @param {String} url ダウンロードするURL 312 | * @param {NicoDownloaderClass} NicoDownloader 313 | * @returns {Object} Blob 314 | */ 315 | //////////////////////////////////////////////////////////////////////// 316 | async function Downloadblob(url, NicoDownloader) { 317 | //TSの取得 318 | let res = await fetch_retry( 319 | url, 320 | NicoDownloader, 321 | { credentials: "include" }, 322 | 100 323 | ); 324 | 325 | let blob = res.blob(); 326 | DebugPrint("BLOBgetEnd:" + url); 327 | return blob; 328 | } 329 | 330 | //////////////////////////////////////////////////////////////////////// 331 | /** 332 | * URLからダウンロードし、Uint8Arrayを返す 333 | * @param {String} url ダウンロードするURL 334 | * @param {NicoDownloaderClass} NicoDownloader 335 | * @returns {Object} Uint8Array 336 | */ 337 | //////////////////////////////////////////////////////////////////////// 338 | async function DownloadUint8Array(url, NicoDownloader) { 339 | let blob = await Downloadblob(url, NicoDownloader); 340 | let byte = null; 341 | await blob.arrayBuffer().then((data) => { 342 | byte = new Uint8Array(data); 343 | }); 344 | return byte; 345 | } 346 | 347 | //////////////////////////////////////////////////////////////////////// 348 | /** 349 | * 変換処理してファイルを返す 350 | * @param {Core} Core 351 | * @param {String} m3u8name 352 | * @param {NicoDownloaderClass} NicoDownloader 353 | * @param {NicovideoClass} Nicovideo 354 | * @returns {Object} file 355 | */ 356 | //////////////////////////////////////////////////////////////////////// 357 | async function Transcode(Core, m3u8name, NicoDownloader, Nicovideo) { 358 | NicoDownloader.ButtonTextWrite("変換中"); 359 | let mode = await Option_setLoading("downFile_setting") || "mp4"; // モードを取得 360 | if (mode == 0) mode = "mp4"; // モードが取得できなかった場合はデフォルトのmp4にする 361 | 362 | console.log(`Current mode: ${mode}`); // モードを確認するログ 363 | const file = await runFFmpeg_m3u8( 364 | Core, 365 | m3u8name, 366 | NicoDownloader, 367 | Nicovideo, 368 | mode 369 | ); 370 | return file; 371 | } 372 | 373 | //////////////////////////////////////////////////////////////////////// 374 | /** 375 | * Option_setLoading関数は、指定された名前のローカルストレージの値を読み込み、localStorageに設定します。 376 | * 377 | * @param {string} name - 読み込むローカルストレージの名前 378 | * @returns {string|number} - 指定された名前のローカルストレージの値。読み込みに失敗した場合は0を返します。 379 | */ 380 | //////////////////////////////////////////////////////////////////////// 381 | function Option_setLoading(name) { 382 | 383 | try { 384 | chrome.storage.local.get(name, function (value) { 385 | //chrome.storage.localから読み出し 386 | localStorage.setItem(name, value[name]); 387 | }) 388 | //return return_val; 389 | return localStorage.getItem(name); 390 | 391 | } catch (error) { 392 | return 0; 393 | } 394 | 395 | } 396 | 397 | //////////////////////////////////////////////////////////////////////// 398 | /** 399 | * リトライ処理を含めたfetch https://qiita.com/ksakiyama134/items/8cfb0cf96d8f7c7be5b3 400 | * @param {String} url ダウンロードするURL 401 | * @param {NicoDownloaderClass} NicoDownloader 402 | * @param {Object} options fetchのオプション 403 | * @param {Number} n リトライ回数 404 | * @returns {Object} fetch 405 | */ 406 | //////////////////////////////////////////////////////////////////////// 407 | async function fetch_retry(url, NicoDownloader, options, n) { 408 | try { 409 | DebugPrint("fetchurl: " + url); 410 | let fetched = await fetch(url, options); 411 | if (fetched.status === 200) { 412 | return fetched; 413 | } else { 414 | DebugPrint("retry:" + url); 415 | NicoDownloader.DownloadFaultNumberAdd(); 416 | sleep(1000); 417 | return await fetch_retry(url, NicoDownloader, options, n - 1); 418 | } 419 | } catch (err) { 420 | NicoDownloader.DownloadFaultNumberAdd(); 421 | sleep(1000); 422 | DebugPrint("retry:" + url); 423 | if (n === 1) throw err; 424 | return await fetch_retry(url, NicoDownloader, options, n - 1); 425 | } 426 | } 427 | 428 | //////////////////////////////////////////////////////////////////////// 429 | /** 430 | * スリープ関数 https://www.sejuku.net/blog/24629 431 | * @param {Number} waitMsec スリープ時間 432 | */ 433 | //////////////////////////////////////////////////////////////////////// 434 | function sleep(waitMsec) { 435 | var startMsec = new Date(); 436 | 437 | // 指定ミリ秒間だけループさせる(CPUは常にビジー状態) 438 | while (new Date() - startMsec < waitMsec); 439 | } 440 | -------------------------------------------------------------------------------- /nico_downloader/func/ndl.js: -------------------------------------------------------------------------------- 1 | //めっちゃ重要なデータ 2 | /* 3 | VideoData 4 | VideoData.Video_title : 動画のタイトルのクラス名 5 | VideoData.Video_title_Element : タイトルの場所のクエリで、ボタンを追加する場所 6 | VideoData.Video_DLlink : ボタンの内部構造のクエリ 7 | VideoData.SystemMessageContainer : SystemMessageのクエリ 8 | VideoData.PlayerSettingQuery : 設定ボタンのクエリ 9 | VideoData.PlayerSettingClass : 設定ボタンのクラス名 10 | VideoData.SystemMessageClass : SystemMessageのクラス名 11 | VideoData.SystemMessageQuery : SystemMessageのクエリ 12 | VideoData.DLButton : ダウンロードボタンのCSSとかHTML 13 | VideoData.DLButton.a : ダウンロードボタンのHTMLの前半 14 | VideoData.DLButton.b : ダウンロードボタンのHTMLの中身 15 | VideoData.DLButton.c : ダウンロードボタンのHTMLの後半 16 | 17 | */ 18 | 19 | const VideoData = { 20 | // 動画のタイトルのクラス名 21 | Video_title: 'fs_xl fw_bold', 22 | 23 | // タイトルの場所のクエリで、ボタンを追加する場所 24 | //Video_title_Element: 'd_flex justify_space-between items_flex-start gap_x3 w_100%', 25 | //Video_title_Element: 'd_flex jc_space-between ai_flex-start gap_x3 w_100%',//2024-09-06 26 | Video_title_Element: 'd_flex jc_space-between ai_flex-start gap_var(--watch-video-information-gap) w_100%',//2025-02-22 27 | 28 | //Video_title_Element: 'd_flex w_[268px] gap_base items_center', 29 | 30 | //ボタンの内部構造のクエリ 31 | Video_DLlink: { 32 | p: 'Dlink', 33 | div_class: 'd_flex justify_flex-start', 34 | a: 'DLlink_a', 35 | li: 'DLlink_li', 36 | a2: 'downloadlink' 37 | }, 38 | 39 | // SystemMessageのクエリ 40 | SystemMessageContainer: 'c_monotone.L80',//2024-09-06 41 | 42 | // 設定ボタンのクエリ 43 | PlayerSettingQuery: '[aria-label="設定"]', 44 | 45 | // 設定ボタンのクラス名 46 | PlayerSettingClass: 'h_[calc(100vh_-_{sizes.commonHeader.inViewHeight}_-_{sizes.webHeader.height}_-_{spacing.x12})] max-h_[480px] rounded_m bg_layer.surfaceHighEm d_flex flex_column overflow_hidden shadow_base',//2024-09-06 47 | 48 | // SystemMessageのクエリ 49 | SystemMessageQuery: '[class^="cursor_pointer d_inline-flex ai_center jc_center gap_x0_5 px_x2 bdr_full fs_s fw_bold button-color_base white-space_nowrap us_none hover:cursor_pointer disabled:pointer-events_none [&_>_svg]:w_auto [&_>_svg]:h_x3 h_x3 [&_svg]:d_none"]',//2024-09-06 50 | 51 | // ダウンロードボタンのCSSとかHTML 52 | DLButton: { 53 | a: " 153 | 159 |
160 |

設定

161 | 162 |
163 | 164 |
165 | 166 |

- hlsモードで保存をするための初期設定が必要です。

167 |

- 初期設定はONです。OFFにすると支援表示が消えダウンロードができるようになります。

168 |

現在の設定:

169 |

170 | 175 |

176 |
177 |
178 | 179 |

- 「名前を付けて保存」画面でデフォルトで命名されるファイル名を設定できます

180 |

181 |

現在の設定:

182 |

188 |
189 |
190 | 191 |

- 表示言語を選択してください。

192 |

- 設定画面は日本語のみ対応しています。

193 |

現在の設定:

194 |

195 | 199 |

200 |
201 |
202 | 203 |

ー 保存形式を選択してください。

204 |

ー mp4とaacで変更できます。

205 |

現在の設定:

206 |

207 | 211 |

212 |
213 |


214 |
215 | プロフェッショナル設定(ここの設定についてはサポートしません) 216 |
217 | 218 |

- 特定のパターンでのみ反応するように変更できます。

219 |

- Javascriptの正規表現で記載してください。

220 |

現在の設定:

221 |

https://www.nicovideo.jp/watch/

222 |
223 | 224 | 225 |
226 | 227 |

- リンクの作成ができた時点で自動で保存処理が走るようになります。

228 |

- 鬱陶しい時はOFFにしましょう

229 |

現在の設定:

230 |

231 | 235 |

236 |
237 |


238 | 239 |
240 | 241 |

- デバッグモードです。

242 |

現在の設定:

243 |

244 | 248 |

249 |
250 |


251 |
252 |


253 | 254 | 255 | 256 |
257 |
258 |

 

259 |

260 |
261 |
262 | 263 | 264 | 265 |
266 | 270 |
271 | 不具合・バグ報告・ソフトウェアについての要望などはGithubから
272 | こちらにご報告いただけると迅速な対応が可能です。 273 |
274 |
275 | 276 | 277 |

vX.X.X.X

278 |
279 |
280 |
281 |
282 | 283 | 284 | 285 | 286 | -------------------------------------------------------------------------------- /nico_downloader/options.js: -------------------------------------------------------------------------------- 1 | /* 2 | LocalStorageで保存される値について 3 | 4 | キー デフォルト値 内容 5 | "newloading" undefined 一度でも設定したことがあるか? 6 | "video_downloading" 0 デフォルト保存名設定 7 | "video_pattern" sm[0-9]{1,} 反応するURL設定名 8 | "video_autosave" 0 1だと自動で保存処理が走ります 9 | "video_hlssave" 0 0だと初期設定、1だと低速、2だと高速モード 10 | "debug" 0 1だとデバッグ出力あり 11 | "language_setting" ja 言語設定 12 | "downFile_setting" mp4 保存ファイル形式(採用) 13 | */ 14 | 15 | 16 | function Option_setWriting(name, value) { 17 | //ローカルストレージに書き込みを行います 18 | localStorage.setItem(name, value); 19 | chrome.storage.local.set({ 20 | [name]: value 21 | }, function () { 22 | //chrome.storage.localに保存 23 | }) 24 | return true; 25 | } 26 | 27 | function Option_setLoading(name) { 28 | //ローカルストレージより読み込みを行います 29 | //return localStorage.getItem(name);//これだとだめ 30 | 31 | try { 32 | chrome.storage.local.get(name, function (value) { 33 | //chrome.storage.localから読み出し 34 | localStorage.setItem(name, value[name]); 35 | }) 36 | //return return_val; 37 | 38 | if (localStorage.getItem(name) === "undefined") { 39 | return 0; 40 | } 41 | return localStorage.getItem(name); 42 | 43 | } catch (error) { 44 | return 0; 45 | } 46 | 47 | } 48 | 49 | //オプション値読み込み用関数 50 | function setOption(name) { 51 | try { 52 | if (Option_setLoading(name) === "undefined") { 53 | return 0; 54 | } else { 55 | 56 | return Option_setLoading(name); 57 | } 58 | 59 | } catch (error) { 60 | DebugPrint("SetOption:" + error) 61 | return 0; 62 | } 63 | } 64 | 65 | function newload() { 66 | let newloading = 0; 67 | 68 | 69 | //default値をここへ 70 | if (isNullOrUndefined(Option_setLoading("newloading"))) { 71 | defalt_dataWrite(); 72 | } 73 | newloading = Option_setLoading("newloading") 74 | } 75 | 76 | function defalt_dataWrite() { 77 | Option_setWriting("newloading", "1"); 78 | Option_setWriting("video_downloading", "0"); 79 | Option_setWriting("video_pattern", "sm[0-9]{1,}"); 80 | Option_setWriting("video_autosave", "0"); 81 | Option_setWriting("debug", "0"); 82 | Option_setWriting("video_hlssave", "0"); 83 | Option_setWriting("language_setting", "ja"); 84 | Option_setWriting("downFile_setting", "mp4"); //mp4として 85 | Options_Save(); 86 | } 87 | 88 | function Options_onload() { 89 | //オプション設定ページ表示時 90 | 91 | //オプションの値を読み込み 92 | try { 93 | LoadOption("video_downloading"); 94 | LoadOption("video_pattern"); 95 | LoadOption("video_autosave"); 96 | LoadOption("video_hlssave"); 97 | LoadOption("debug"); 98 | LoadOption("language_setting"); 99 | LoadOption("downFile_setting") || "mp4"; 100 | } catch (error) { 101 | Default_click(); 102 | Options_Save(); 103 | } 104 | 105 | } 106 | 107 | function LoadOption(name) { 108 | console.log(setOption(name)) 109 | if (typeof setOption(name) === "undefined") { 110 | 111 | } else { 112 | document.getElementById(name).value = setOption(name); 113 | } 114 | } 115 | 116 | function isNullOrUndefined(o) { 117 | return (o === undefined || o === null); 118 | } 119 | 120 | 121 | function DebugPrint(text) { 122 | if (setOption("debug") === "1") { 123 | console.log("debug:" + text); 124 | } 125 | } -------------------------------------------------------------------------------- /nico_downloader/options_menu.js: -------------------------------------------------------------------------------- 1 | //非保存フラグ 2 | let save_flag = true; 3 | 4 | //ロード時 5 | window.onload = function () { 6 | newload(); 7 | Options_onload(); 8 | SoftVersionWrite(); 9 | 10 | //10ミリ秒ごとの処理を設定 11 | const intervalId = setInterval(() => { 12 | if (save_flag == true) { 13 | Options_view_select("video_downloading"); 14 | Options_view_input("video_pattern"); 15 | Options_view_select("video_autosave"); 16 | Options_view_select("video_hlssave"); 17 | Options_view_select("debug"); 18 | Options_view_select("language_setting"); 19 | Options_view_select("downFile_setting"); 20 | } 21 | save_flag = false; 22 | }, 10); 23 | } 24 | 25 | function Options_view_select(name) { 26 | let name_func = name; 27 | 28 | chrome.storage.local.get(name_func, function (result) { 29 | // chrome.storage.local から name_func に対応する値を取得 30 | const storedValue = result[name_func]; 31 | 32 | // `optionValue` に取得した値かデフォルト値を設定 33 | const optionValue = storedValue !== undefined ? storedValue : "0"; 34 | 35 | const selectElement = document.getElementById(name_func); 36 | if (selectElement) { 37 | // `optionValue`が存在するか確認して`value`を設定 38 | selectElement.value = optionValue; 39 | localStorage.setItem(name_func, optionValue); 40 | 41 | // 表示書き換え 42 | const optionsArray = Array.from(selectElement.options); // optionsを配列として取得 43 | const selectedOption = optionsArray.find(option => option.value === optionValue); 44 | 45 | if (selectedOption) { 46 | const nowtext = "現在の設定:" + selectedOption.innerText; 47 | const rewrite = name_func + "_now_setting"; 48 | 49 | const displayElement = document.getElementById(rewrite); 50 | if (displayElement) { 51 | displayElement.innerText = nowtext; 52 | } else { 53 | console.error(`Display element with id '${rewrite}' not found.`); 54 | } 55 | } else { 56 | console.error(`Option with value '${optionValue}' not found in select element.`); 57 | } 58 | } else { 59 | console.error(`Select element with id '${name_func}' not found.`); 60 | } 61 | }); 62 | } 63 | 64 | function Options_view_input(name) { 65 | name_func = name; 66 | chrome.storage.local.get(name_func, function (value) { 67 | //chrome.storage.localから読み出し 68 | document.getElementById(name_func).value = setOption(name_func); 69 | localStorage.setItem(name_func, setOption(name_func)); 70 | 71 | //表示書き換え 72 | let nowtext = "現在の設定:" + setOption(name_func); 73 | document.getElementById(name_func + "_now_setting").innerText = nowtext; 74 | }) 75 | } 76 | 77 | function Options_Save() { 78 | //オプション設定保存時 79 | 80 | //オプションの値を書き込み 81 | Option_setWritingByID("video_downloading"); 82 | Option_setWritingByID("video_pattern"); 83 | Option_setWritingByID("debug"); 84 | Option_setWritingByID("video_autosave"); 85 | Option_setWritingByID("video_hlssave"); // 86 | Option_setWritingByID("language_setting"); 87 | Option_setWritingByID("downFile_setting"); 88 | 89 | 90 | //保存日時 91 | let now = new Date(); 92 | document.getElementById("saved").innerText = "保存日時:" + now.toLocaleString(); 93 | 94 | //非保存フラグ 95 | save_flag = true; 96 | 97 | } 98 | 99 | function Option_setWritingByID(ID) { 100 | Option_setWriting(ID, document.getElementById(ID).value); 101 | } 102 | 103 | function Default_click() { 104 | //デフォルト設定を入力 105 | document.getElementById("form").value = document.getElementById("form").reset(); 106 | } 107 | 108 | function SoftVersion() { 109 | let manifest = chrome.runtime.getManifest(); 110 | return manifest['version']; 111 | } 112 | 113 | function SoftVersionWrite() { 114 | let ver = SoftVersion(); 115 | document.getElementById("version").innerText = `バージョン:` + ver; 116 | } 117 | 118 | function SystemMessageOpenButton() { 119 | document.getElementById('system_message_open').style = 'display: block'; 120 | } 121 | 122 | //システムメッセージを開きダウンロードする方法 123 | document.getElementById("system_message_open_button").onclick = SystemMessageOpenButton; 124 | 125 | //保存ボタンクリック時 126 | document.getElementById("save_button").onclick = Options_Save; 127 | document.getElementById("default_val").onclick = Default_click; -------------------------------------------------------------------------------- /tool/actionTrackId_make.js: -------------------------------------------------------------------------------- 1 | 2 | function genActionTrackID() { 3 | //ニコニコにあったやつwatch.XXXXXXXXXXX.min.js 4 | for (var e = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789".split(""), t = "", n = 0; n < 10; n++) 5 | t += e[Math.floor(Math.random() * e.length)]; 6 | return t + "_" + Date.now() 7 | } 8 | console.log(genActionTrackID()); -------------------------------------------------------------------------------- /tool/api.nico: -------------------------------------------------------------------------------- 1 | https://public.nvcomment.nicovideo.jp/v1/threads 2 | https://www.nicovideo.jp/watch/sm9?responseType=json -------------------------------------------------------------------------------- /tool/newhls_encode.js: -------------------------------------------------------------------------------- 1 | //ffmpegだとこんな感じ 2 | //ffmpeg -allowed_extensions ALL -protocol_whitelist file,http,https,tcp,tls,crypto -i video-h264-720p.m3u8 -c copy "output.ts" 3 | //ローカルで変換するためにvideo-h264-XXXp.m3u8のファイルの中身を書き換える 4 | //https://asset.domand.nicovideo.jp/XXXXXXXXXXXXXXXXXX/video/1/video-h264-720p/を削除 5 | //https://delivery.domand.nicovideo.jp/hls/XXXXXXXXXXXXXXXXX/keys/を削除 6 | //あとは全部ローカルに保存して結合すると映像のみができあがる 7 | 8 | 9 | 10 | //https://www.nicovideo.jp/watch/sm37845720?responseType=json 11 | //で取得できる 12 | 13 | 14 | 15 | /* 16 | GetWatchthreadKey_and_Moviedata_toJSON(video_sm).then((jsondata) => { 17 | const threadKey = JSON_to_threadKey(jsondata); 18 | DebugPrint("threadKey:" + threadKey); 19 | }) 20 | */ 21 | 22 | async function GetWatchthreadKey_and_Moviedata_toJSON(smid) { 23 | const URL = 'https://www.nicovideo.jp/watch/' + smid + '?responseType=json' 24 | // dataExist data.media.domand.accessRightKey 25 | 26 | 27 | 28 | 29 | const dataJSON = await ( 30 | await fetch(URL, 31 | { 32 | "headers": { 33 | "accept": "*/*", 34 | "accept-language": "ja-JP,ja;q=0.9", 35 | "sec-ch-ua": "\"Google Chrome\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"", 36 | "sec-ch-ua-mobile": "?1", 37 | "sec-ch-ua-platform": "\"Windows\"", 38 | "sec-fetch-dest": "empty", 39 | "sec-fetch-mode": "cors", 40 | "sec-fetch-site": "same-site" 41 | }, 42 | "referrer": "https://www.nicovideo.jp/", 43 | "referrerPolicy": "strict-origin-when-cross-origin", 44 | "body": null, 45 | "method": "GET", 46 | "mode": "cors", 47 | "credentials": "include" 48 | } 49 | )).json(); 50 | 51 | return dataJSON; 52 | } 53 | function JSON_to_threadKey(JSON) { 54 | const threadKey = JSON.data.response.media.domand.accessRightKey; 55 | return threadKey; 56 | } 57 | async function GetHlsData(JSON) { 58 | const hlsData = JSON.data.response.media.delivery.hls; 59 | return hlsData; 60 | } -------------------------------------------------------------------------------- /tool/old.js: -------------------------------------------------------------------------------- 1 | //ここは使わなくなった古い関数の置き場 2 | /* 3 | function masterm3u8_addURL(url, urldir) { 4 | 5 | return String(urldir.match(/(https.).*(master.m3u8?.)/g)).replace('master.m3u8?', '') + url; 6 | } 7 | function playlistm3u8_addURL(url, urldir) { 8 | 9 | return String(urldir.match(/(https.).*(playlist.m3u8?.)/g)).replace('playlist.m3u8?', '') + url; 10 | } 11 | function MovieDownload_dmcnico(masterURL, video_sm, video_name) { 12 | 13 | //ダウンロード中フラグ立てる 14 | downloading = true; 15 | 16 | const xhr_master = new XMLHttpRequest();//XMLHttpRequest 17 | let masterRawMessage, playlistURL 18 | 19 | xhr_master.open('GET', masterURL); //GETを作る 20 | xhr_master.send(); //リクエストを投げる 21 | xhr_master.onreadystatechange = function () { 22 | if (xhr_master.readyState === 4 && xhr_master.status === 200) { 23 | 24 | if (video_link_smid == video_sm) { 25 | return false; 26 | } 27 | //ここで一回止める 28 | //読み込み形跡を残す 29 | video_link_smid = video_sm; 30 | DebugPrint("smid上書き"); 31 | 32 | //取得完了したらここに飛ぶ 33 | masterRawMessage = this.responseText; 34 | 35 | //文字列を行ごとに分解する 36 | let masterURLGyou = masterRawMessage.split(/\r\n|\n/); 37 | //3行目は常に高画質っぽいのでそれだけ抽出 38 | playlistURL = String(masterURL.match(/(https.).*(master.m3u8?.)/g)).replace('master.m3u8?', '') + masterURLGyou[2]; 39 | DebugPrint("playlistURL: " + playlistURL); 40 | 41 | 42 | //playlistURLにはダウンロードすべきm3u8のURLが入ってるのでそれをダウンロード 43 | const xhr_playlist = new XMLHttpRequest(); 44 | xhr_playlist.open('GET', playlistURL); 45 | xhr_playlist.send(); 46 | xhr_playlist.onreadystatechange = function () { 47 | if (xhr_master.readyState === 4 && xhr_master.status === 200) { 48 | //取得完了したらここに飛ぶ 49 | let playlistRawMessage = this.responseText; 50 | 51 | 52 | 53 | //https://stabucky.com/wp/archives/10419 54 | playlistRawMessage = playlistRawMessage.trim(); 55 | playlistRawMessage = playlistRawMessage.replace(/(\r?\n)+/g, "\n"); 56 | 57 | const playlistMessage = playlistRawMessage.split(/\r\n|\n/); 58 | DebugPrint(playlistMessage); 59 | 60 | 61 | //神 of GOD 62 | //https://github.com/naari3/nico-downloader-ffmpeg/blob/main/src/background.ts 63 | //ご協力感謝します 64 | 65 | // playlistのアイテムを全部読み込む 66 | 67 | //読み込んだTSファイルの置き場所配列 68 | let TSURLs = []; 69 | let fps = 60; 70 | 71 | for (let i = 0; i < playlistMessage.length; i++) { 72 | let element = playlistMessage[i]; 73 | if (element.match(/#/)) { 74 | //#が入ってる行は飛ばす 75 | 76 | if (element.match(/FRAME-RATE=([\d.]+)/)) { 77 | fps = element.match(/FRAME-RATE=([\d.]+)/); 78 | } 79 | 80 | } else if (element == "") { 81 | //空行は飛ばす 82 | } else { 83 | //TSURLの取得 84 | const TSURL = String(playlistURL.match(/(https.).*(playlist.m3u8?.)/g)).replace('playlist.m3u8?', '') + element; 85 | TSURLs.push(TSURL); 86 | } 87 | 88 | if (element.match(/ENDLIST/)) { 89 | //ENDLISTが入ってる行まで読み込めばOK 90 | DebugPrint("TSURLs.length:" + TSURLs.length); 91 | if (TSURLs.length == 0) { 92 | return; 93 | } 94 | 95 | documentWriteText(video_name + "をダウンロード"); 96 | documentWriteOnclick(DLstartOnclick(TSURLs, video_sm, video_name, String(fps))); 97 | 98 | } 99 | } 100 | 101 | //フラグ戻す 102 | downloading = false; 103 | 104 | //読み込み形跡を残す 105 | video_link_smid = video_sm; 106 | DebugPrint("smid上書き"); 107 | 108 | } 109 | } 110 | 111 | 112 | } 113 | } 114 | } 115 | 116 | 117 | function MovieDownload_dmcnico(masterURL, video_sm, video_name) { 118 | 119 | //ダウンロード中フラグ立てる 120 | downloading = true; 121 | 122 | const xhr_master = new XMLHttpRequest();//XMLHttpRequest 123 | let masterRawMessage, playlistURL 124 | 125 | xhr_master.open('GET', masterURL); //GETを作る 126 | xhr_master.send(); //リクエストを投げる 127 | xhr_master.onreadystatechange = function () { 128 | if (xhr_master.readyState === 4 && xhr_master.status === 200) { 129 | 130 | if (video_link_smid == video_sm) { 131 | return false; 132 | } 133 | //ここで一回止める 134 | //読み込み形跡を残す 135 | video_link_smid = video_sm; 136 | DebugPrint("smid上書き"); 137 | 138 | //取得完了したらここに飛ぶ 139 | masterRawMessage = this.responseText; 140 | 141 | //文字列を行ごとに分解する 142 | let masterURLGyou = masterRawMessage.split(/\r\n|\n/); 143 | //3行目は常に高画質っぽいのでそれだけ抽出 144 | playlistURL = String(masterURL.match(/(https.).*(master.m3u8?.)/g)).replace('master.m3u8?', '') + masterURLGyou[2]; 145 | DebugPrint("playlistURL: " + playlistURL); 146 | 147 | 148 | //playlistURLにはダウンロードすべきm3u8のURLが入ってるのでそれをダウンロード 149 | const xhr_playlist = new XMLHttpRequest(); 150 | xhr_playlist.open('GET', playlistURL); 151 | xhr_playlist.send(); 152 | xhr_playlist.onreadystatechange = function () { 153 | if (xhr_master.readyState === 4 && xhr_master.status === 200) { 154 | //取得完了したらここに飛ぶ 155 | let playlistRawMessage = this.responseText; 156 | 157 | 158 | 159 | //https://stabucky.com/wp/archives/10419 160 | playlistRawMessage = playlistRawMessage.trim(); 161 | playlistRawMessage = playlistRawMessage.replace(/(\r?\n)+/g, "\n"); 162 | 163 | const playlistMessage = playlistRawMessage.split(/\r\n|\n/); 164 | DebugPrint(playlistMessage); 165 | 166 | 167 | //神 of GOD 168 | //https://github.com/naari3/nico-downloader-ffmpeg/blob/main/src/background.ts 169 | //ご協力感謝します 170 | 171 | // playlistのアイテムを全部読み込む 172 | 173 | //読み込んだTSファイルの置き場所配列 174 | let TSURLs = []; 175 | let fps = 60; 176 | 177 | for (let i = 0; i < playlistMessage.length; i++) { 178 | let element = playlistMessage[i]; 179 | if (element.match(/#/)) { 180 | //#が入ってる行は飛ばす 181 | 182 | if (element.match(/FRAME-RATE=([\d.]+)/)) { 183 | fps = element.match(/FRAME-RATE=([\d.]+)/); 184 | } 185 | 186 | } else if (element == "") { 187 | //空行は飛ばす 188 | } else { 189 | //TSURLの取得 190 | const TSURL = String(playlistURL.match(/(https.).*(playlist.m3u8?.)/g)).replace('playlist.m3u8?', '') + element; 191 | TSURLs.push(TSURL); 192 | } 193 | 194 | if (element.match(/ENDLIST/)) { 195 | //ENDLISTが入ってる行まで読み込めばOK 196 | DebugPrint("TSURLs.length:" + TSURLs.length); 197 | if (TSURLs.length == 0) { 198 | return; 199 | } 200 | 201 | documentWriteText(video_name + "をダウンロード"); 202 | documentWriteOnclick(DLstartOnclick(TSURLs, video_sm, video_name, String(fps))); 203 | 204 | } 205 | } 206 | 207 | //フラグ戻す 208 | downloading = false; 209 | 210 | //読み込み形跡を残す 211 | video_link_smid = video_sm; 212 | DebugPrint("smid上書き"); 213 | 214 | } 215 | } 216 | 217 | 218 | } 219 | } 220 | } 221 | 222 | async function MovieDownload_dmcnico(masterURL, video_sm, video_name) { 223 | 224 | //ダウンロード中フラグ立てる 225 | downloading = true; 226 | 227 | const Firstm3u8_body = await TextDownload_withCookie(masterURL); 228 | DebugPrint(Firstm3u8_body); 229 | const Firstm3u8_body_json = m3u8_Parse(Firstm3u8_body); 230 | 231 | 232 | const video_m3u8_URL = masterm3u8_addURL(Firstm3u8_body_json["EXT-X-STREAM-INF"][0]['URI'], masterURL); 233 | const video_m3u8_body = await TextDownload_withCookie(video_m3u8_URL); 234 | const video_m3u8_body_json = m3u8_Parse(video_m3u8_body); 235 | 236 | 237 | let TSURLs = makeTSURLs_dmcnicovideo(video_m3u8_body_json); 238 | for (let i = 0; i < TSURLs.length; i++) { 239 | TSURLs[i] = playlistm3u8_addURL(TSURLs[i], video_m3u8_URL); 240 | } 241 | 242 | 243 | let TSFilenames = makeTSFilenames(TSURLs) 244 | 245 | let replace_video = video_m3u8_body.replace(/[?][\w=\-&_.~]+/g, '').replace('1/ts/', ''); 246 | let replace_Firstm3u8 = Firstm3u8_body.replace(/[?][\w=\-&_.~]+/g, '').replace('1/ts/', '');; 247 | let m3u8s = [replace_video, replace_Firstm3u8, 248 | makeFilename(video_m3u8_URL).replace('1/ts/', ''), makeFilename(masterURL)]; 249 | 250 | 251 | 252 | DebugPrint(String(TSURLs)) 253 | documentWriteText(video_name + "をダウンロード"); 254 | documentWriteOnclick(DLstartOnclick(TSURLs, TSFilenames, m3u8s, video_sm, video_name)); 255 | 256 | 257 | 258 | } 259 | 260 | function makeTSURLs_dmcnicovideo(video_m3u8_body_json) { 261 | let TSURLs = []; 262 | for (let i = 0; i < video_m3u8_body_json['EXTINF'].length; i++) { 263 | TSURLs.push(video_m3u8_body_json['EXTINF'][i]['URI']); 264 | } 265 | return TSURLs; 266 | } 267 | */ -------------------------------------------------------------------------------- /tool/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 設定 - nico downloader 14 | 15 | 16 | 17 |
18 |

19 |

設定 - nico downloader

20 |

21 |
22 |
23 |
24 | 25 |

26 |

27 |

28 |

保存方法の簡易説明

29 |

1.下記「初期設定モード」をOFFにし、ページの一番下にある「保存」ボタンを押下します。

30 |

2.動画ページを開き、動画の右下あたりにある保存ボタンを押します。

31 |

3.しばらくダウンロードと変換処理に時間がかかります。

32 |

4.動画が保存されます。既定のフォルダに自動保存または保存ダイアログが表示されます。(Chromeの保存設定によります)

33 |
34 | 35 |
36 | 37 |

- hlsモードで保存をするための初期設定が必要です。

38 |

- 初期設定はONです。OFFにすると支援表示が消えダウンロードができるようになります。

39 |

現在の設定:

40 |

41 | 46 |

47 |
48 |


49 |
50 | 51 |

- 「名前を付けて保存」画面でデフォルトで命名されるファイル名を設定できます

52 |

53 |

現在の設定:

54 |

60 |
61 |


62 |
63 | プロフェッショナル設定(ここの設定についてはサポートしません) 64 |
65 | 66 |

- 特定のパターンでのみ反応するように変更できます。

67 |

- Javascriptの正規表現で記載してください。

68 |

現在の設定:

69 |

https://www.nicovideo.jp/watch/

71 |
72 | 73 | 74 |
75 | 76 |

- リンクの作成ができた時点で自動で保存処理が走るようになります。

77 |

- 鬱陶しい時はOFFにしましょう

78 |

現在の設定:

79 |

80 | 84 |

85 |
86 |


87 | 88 |
89 | 90 |

- デバッグモードです。

91 |

現在の設定:

92 |

93 | 97 |

98 |
99 |


100 |
101 |


102 | 103 | 104 | 105 |
106 |


107 |
108 |

 

109 |

110 |
111 | 112 | 113 |
不具合・バグ報告・ソフトウェアについての要望などはTwitterから
114 |
115 | 116 |

117 |
118 |
119 | 120 | 121 | 122 | 123 | 124 | --------------------------------------------------------------------------------