Gregory Leeman 1 month ago
commit
bf626aa7df
  1. BIN
      .DS_Store
  2. 1
      asbplayer-extension/265.js
  3. 1
      asbplayer-extension/389.js
  4. 1
      asbplayer-extension/53.js
  5. 1
      asbplayer-extension/894.js
  6. 20
      asbplayer-extension/_locales/de/messages.json
  7. 29
      asbplayer-extension/_locales/en/messages.json
  8. 29
      asbplayer-extension/_locales/es/messages.json
  9. 29
      asbplayer-extension/_locales/ja/messages.json
  10. 23
      asbplayer-extension/_locales/pl/messages.json
  11. 29
      asbplayer-extension/_locales/pt_BR/messages.json
  12. 29
      asbplayer-extension/_locales/zh_CN/messages.json
  13. 2
      asbplayer-extension/active-tab-permission-request-ui.js
  14. 56
      asbplayer-extension/active-tab-permission-request-ui.js.LICENSE.txt
  15. 2
      asbplayer-extension/anki-ui.js
  16. 77
      asbplayer-extension/anki-ui.js.LICENSE.txt
  17. 293
      asbplayer-extension/asbplayer-locales/de.json
  18. 293
      asbplayer-extension/asbplayer-locales/en.json
  19. 294
      asbplayer-extension/asbplayer-locales/es.json
  20. 293
      asbplayer-extension/asbplayer-locales/ja.json
  21. 293
      asbplayer-extension/asbplayer-locales/pl.json
  22. 293
      asbplayer-extension/asbplayer-locales/pt_BR.json
  23. 293
      asbplayer-extension/asbplayer-locales/zh_CN.json
  24. 1
      asbplayer-extension/asbplayer.js
  25. BIN
      asbplayer-extension/assets/icon128.png
  26. BIN
      asbplayer-extension/assets/icon16.png
  27. BIN
      asbplayer-extension/assets/icon32.png
  28. BIN
      asbplayer-extension/assets/icon48.png
  29. BIN
      asbplayer-extension/assets/image.png
  30. 30
      asbplayer-extension/background-page.html
  31. 2
      asbplayer-extension/background-page.js
  32. 1
      asbplayer-extension/background-page.js.LICENSE.txt
  33. 2
      asbplayer-extension/background.js
  34. 1
      asbplayer-extension/background.js.LICENSE.txt
  35. 12
      asbplayer-extension/ftue-ui.html
  36. 2
      asbplayer-extension/ftue-ui.js
  37. 58
      asbplayer-extension/ftue-ui.js.LICENSE.txt
  38. 118
      asbplayer-extension/manifest.json
  39. 1
      asbplayer-extension/mp3-encoder-worker.js
  40. 1
      asbplayer-extension/page.js
  41. 76
      asbplayer-extension/pages.json
  42. 1
      asbplayer-extension/pages/amazon-prime-page.js
  43. 1
      asbplayer-extension/pages/bandai-channel-page.js
  44. 2
      asbplayer-extension/pages/disney-plus-page.js
  45. 1
      asbplayer-extension/pages/disney-plus-page.js.LICENSE.txt
  46. 1
      asbplayer-extension/pages/hulu-page.js
  47. 1
      asbplayer-extension/pages/netflix-page.js
  48. 1
      asbplayer-extension/pages/tver-page.js
  49. 1
      asbplayer-extension/pages/unext-page.js
  50. 1
      asbplayer-extension/pages/util.js
  51. 1
      asbplayer-extension/pages/youtube-page.js
  52. 1
      asbplayer-extension/pgs-parser-worker.js
  53. 12
      asbplayer-extension/popup-ui.html
  54. 2
      asbplayer-extension/popup-ui.js
  55. 88
      asbplayer-extension/popup-ui.js.LICENSE.txt
  56. 12
      asbplayer-extension/settings-ui.html
  57. 2
      asbplayer-extension/settings-ui.js
  58. 88
      asbplayer-extension/settings-ui.js.LICENSE.txt
  59. 13
      asbplayer-extension/side-panel.html
  60. 2
      asbplayer-extension/side-panel.js
  61. 67
      asbplayer-extension/side-panel.js.LICENSE.txt
  62. 2
      asbplayer-extension/video-data-sync-ui.js
  63. 77
      asbplayer-extension/video-data-sync-ui.js.LICENSE.txt
  64. 2
      asbplayer-extension/video-select-ui.js
  65. 56
      asbplayer-extension/video-select-ui.js.LICENSE.txt
  66. 145
      asbplayer-extension/video.css
  67. 2
      asbplayer-extension/video.js
  68. 12
      asbplayer-extension/video.js.LICENSE.txt
  69. 14
      google-lens-search/background.js
  70. BIN
      google-lens-search/icon.png
  71. 13
      google-lens-search/manifest.json
  72. BIN
      image-saver/icon.png
  73. 39
      image-saver/main.js
  74. 19
      image-saver/manifest.json
  75. BIN
      media-helper/.DS_Store
  76. 41
      media-helper/background.js
  77. 143
      media-helper/element.js
  78. BIN
      media-helper/icon.png
  79. 0
      media-helper/icon.svg
  80. 10
      media-helper/index.html
  81. 31
      media-helper/manifest.json
  82. 1
      media-helper/node_modules/.bin/autoprefixer
  83. 1
      media-helper/node_modules/.bin/browserslist
  84. 1
      media-helper/node_modules/.bin/cssesc
  85. 1
      media-helper/node_modules/.bin/glob
  86. 1
      media-helper/node_modules/.bin/jiti
  87. 1
      media-helper/node_modules/.bin/nanoid
  88. 1
      media-helper/node_modules/.bin/node-which
  89. 1
      media-helper/node_modules/.bin/resolve
  90. 1
      media-helper/node_modules/.bin/sucrase
  91. 1
      media-helper/node_modules/.bin/sucrase-node
  92. 1
      media-helper/node_modules/.bin/tailwind
  93. 1
      media-helper/node_modules/.bin/tailwindcss
  94. 1
      media-helper/node_modules/.bin/update-browserslist-db
  95. 1
      media-helper/node_modules/.bin/yaml
  96. 1521
      media-helper/node_modules/.package-lock.json
  97. 128
      media-helper/node_modules/@alloc/quick-lru/index.d.ts
  98. 263
      media-helper/node_modules/@alloc/quick-lru/index.js
  99. 9
      media-helper/node_modules/@alloc/quick-lru/license
  100. 43
      media-helper/node_modules/@alloc/quick-lru/package.json

BIN
.DS_Store

Binary file not shown.

1
asbplayer-extension/265.js

@ -0,0 +1 @@
(()=>{"use strict";var t,e,n={9894:(t,e,n)=>{var r=n(9053);const s=1152;class i{constructor(t){const e=t.length*t.numberOfChannels*2+44,n=new a(new DataView(new ArrayBuffer(e)));n.setUint32(1179011410),n.setUint32(e-8),n.setUint32(1163280727),n.setUint32(544501094),n.setUint32(16),n.setUint16(1),n.setUint16(t.numberOfChannels),n.setUint32(t.sampleRate),n.setUint32(2*t.sampleRate*t.numberOfChannels),n.setUint16(2*t.numberOfChannels),n.setUint16(16),n.setUint32(1635017060),n.setUint32(e-n.position-4);const s=t.channels;let i=0;for(;n.position<e;){for(let e=0;e<t.numberOfChannels;++e){let t=Math.max(-1,Math.min(1,s[e][i]));t=0|(.5+t<0?32768*t:32767*t),n.setInt16(t)}++i}this.header=r.Q.readHeader(n.dataView),this.samples=new Int16Array(n.dataView.buffer,this.header.dataOffset,this.header.dataLen/2)}}class a{constructor(t){this.dataView=t,this.position=0}setUint16(t){this.dataView.setUint16(this.position,t,!0),this.position+=2}setUint32(t){this.dataView.setUint32(this.position,t,!0),this.position+=4}setInt16(t){this.dataView.setInt16(this.position,t,!0),this.position+=2}}async function o(t){const e=new i(t),n=e.header.channels,a=e.header.sampleRate,o=e.samples;let h,l=null;if(1===n)h=new Int16Array(o);else{if(2!==n)throw new Error("Unsupport number of channels "+n);{let t=[],e=[];for(let n=0;n<o.length;n+=2)t.push(o[n]),e.push(o[n+1]);h=new Int16Array(t),l=new Int16Array(e)}}const c=[],p=new r.d(n,a,192);let u=o.length;for(var f=0;u>=s;f+=s){const t=null===l?null:l.subarray(f,f+s);var w=p.encodeBuffer(h.subarray(f,f+s),t);w.length>0&&c.push(new Int8Array(w)),u-=s}const d=p.flush();return d.length>0&&c.push(new Int8Array(d)),c}onmessage=async t=>{postMessage({command:"finished",buffer:await o(t.data.audioBuffer)})}}},r={};function s(t){var e=r[t];if(void 0!==e)return e.exports;var i=r[t]={exports:{}};return n[t](i,i.exports,s),i.exports}s.m=n,s.x=()=>{var t=s.O(void 0,[53],(()=>s(9894)));return s.O(t)},t=[],s.O=(e,n,r,i)=>{if(!n){var a=1/0;for(c=0;c<t.length;c++){for(var[n,r,i]=t[c],o=!0,h=0;h<n.length;h++)(!1&i||a>=i)&&Object.keys(s.O).every((t=>s.O[t](n[h])))?n.splice(h--,1):(o=!1,i<a&&(a=i));if(o){t.splice(c--,1);var l=r();void 0!==l&&(e=l)}}return e}i=i||0;for(var c=t.length;c>0&&t[c-1][2]>i;c--)t[c]=t[c-1];t[c]=[n,r,i]},s.f={},s.e=t=>Promise.all(Object.keys(s.f).reduce(((e,n)=>(s.f[n](t,e),e)),[])),s.u=t=>t+".js",s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{var t;s.g.importScripts&&(t=s.g.location+"");var e=s.g.document;if(!t&&e&&(e.currentScript&&(t=e.currentScript.src),!t)){var n=e.getElementsByTagName("script");if(n.length)for(var r=n.length-1;r>-1&&!t;)t=n[r--].src}if(!t)throw new Error("Automatic publicPath is not supported in this browser");t=t.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),s.p=t})(),(()=>{var t={265:1,894:1};s.f.i=(e,n)=>{t[e]||importScripts(s.p+s.u(e))};var e=self.webpackChunk_project_extension=self.webpackChunk_project_extension||[],n=e.push.bind(e);e.push=e=>{var[r,i,a]=e;for(var o in i)s.o(i,o)&&(s.m[o]=i[o]);for(a&&a(s);r.length;)t[r.pop()]=1;n(e)}})(),e=s.x,s.x=()=>s.e(53).then(e),s.x()})();

1
asbplayer-extension/389.js

File diff suppressed because one or more lines are too long

1
asbplayer-extension/53.js

File diff suppressed because one or more lines are too long

1
asbplayer-extension/894.js

@ -0,0 +1 @@
(()=>{"use strict";var t,e,n={9894:(t,e,n)=>{var r=n(9053);const s=1152;class i{constructor(t){const e=t.length*t.numberOfChannels*2+44,n=new a(new DataView(new ArrayBuffer(e)));n.setUint32(1179011410),n.setUint32(e-8),n.setUint32(1163280727),n.setUint32(544501094),n.setUint32(16),n.setUint16(1),n.setUint16(t.numberOfChannels),n.setUint32(t.sampleRate),n.setUint32(2*t.sampleRate*t.numberOfChannels),n.setUint16(2*t.numberOfChannels),n.setUint16(16),n.setUint32(1635017060),n.setUint32(e-n.position-4);const s=t.channels;let i=0;for(;n.position<e;){for(let e=0;e<t.numberOfChannels;++e){let t=Math.max(-1,Math.min(1,s[e][i]));t=0|(.5+t<0?32768*t:32767*t),n.setInt16(t)}++i}this.header=r.Q.readHeader(n.dataView),this.samples=new Int16Array(n.dataView.buffer,this.header.dataOffset,this.header.dataLen/2)}}class a{constructor(t){this.dataView=t,this.position=0}setUint16(t){this.dataView.setUint16(this.position,t,!0),this.position+=2}setUint32(t){this.dataView.setUint32(this.position,t,!0),this.position+=4}setInt16(t){this.dataView.setInt16(this.position,t,!0),this.position+=2}}async function o(t){const e=new i(t),n=e.header.channels,a=e.header.sampleRate,o=e.samples;let h,l=null;if(1===n)h=new Int16Array(o);else{if(2!==n)throw new Error("Unsupport number of channels "+n);{let t=[],e=[];for(let n=0;n<o.length;n+=2)t.push(o[n]),e.push(o[n+1]);h=new Int16Array(t),l=new Int16Array(e)}}const c=[],p=new r.d(n,a,192);let u=o.length;for(var f=0;u>=s;f+=s){const t=null===l?null:l.subarray(f,f+s);var w=p.encodeBuffer(h.subarray(f,f+s),t);w.length>0&&c.push(new Int8Array(w)),u-=s}const d=p.flush();return d.length>0&&c.push(new Int8Array(d)),c}onmessage=async t=>{postMessage({command:"finished",buffer:await o(t.data.audioBuffer)})}}},r={};function s(t){var e=r[t];if(void 0!==e)return e.exports;var i=r[t]={exports:{}};return n[t](i,i.exports,s),i.exports}s.m=n,s.x=()=>{var t=s.O(void 0,[53],(()=>s(9894)));return s.O(t)},t=[],s.O=(e,n,r,i)=>{if(!n){var a=1/0;for(c=0;c<t.length;c++){for(var[n,r,i]=t[c],o=!0,h=0;h<n.length;h++)(!1&i||a>=i)&&Object.keys(s.O).every((t=>s.O[t](n[h])))?n.splice(h--,1):(o=!1,i<a&&(a=i));if(o){t.splice(c--,1);var l=r();void 0!==l&&(e=l)}}return e}i=i||0;for(var c=t.length;c>0&&t[c-1][2]>i;c--)t[c]=t[c-1];t[c]=[n,r,i]},s.f={},s.e=t=>Promise.all(Object.keys(s.f).reduce(((e,n)=>(s.f[n](t,e),e)),[])),s.u=t=>t+".js",s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{var t;s.g.importScripts&&(t=s.g.location+"");var e=s.g.document;if(!t&&e&&(e.currentScript&&(t=e.currentScript.src),!t)){var n=e.getElementsByTagName("script");if(n.length)for(var r=n.length-1;r>-1&&!t;)t=n[r--].src}if(!t)throw new Error("Automatic publicPath is not supported in this browser");t=t.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),s.p=t})(),(()=>{var t={894:1,265:1};s.f.i=(e,n)=>{t[e]||importScripts(s.p+s.u(e))};var e=self.webpackChunk_project_extension=self.webpackChunk_project_extension||[],n=e.push.bind(e);e.push=e=>{var[r,i,a]=e;for(var o in i)s.o(i,o)&&(s.m[o]=i[o]);for(a&&a(s);r.length;)t[r.pop()]=1;n(e)}})(),e=s.x,s.x=()=>s.e(53).then(e),s.x()})();

20
asbplayer-extension/_locales/de/messages.json

@ -0,0 +1,20 @@
{
"shortcutMineSubtitleAndOpenDialogDescription": {
"message": "Aktuellen Untertitel extrahieren und Anki-Dialog öffnen. Audiorecorder starten / stoppen"
},
"shortcutMineSubtitleDescription": {
"message": "Aktuellen Untertitel extrahieren. Audiorecorder starten / stoppen"
},
"shortcutSelectSubtitleTrackDescription": {
"message": "Untertitelspuren auswählen"
},
"shortcutTakeScreenshotDescription": {
"message": "Manuellen Screenshot erstellen - dieser überschreibt den automatisierten Screenshot"
},
"shortcutToggleRecordingDescription": {
"message": "Audiorecorder manuell starten / stoppen"
},
"shortcutUpdateLastCardDescription": {
"message": "Zuletzt erstellte Anki-Karte mit aufgezeichnetem Untertitel"
}
}

29
asbplayer-extension/_locales/en/messages.json

@ -0,0 +1,29 @@
{
"extensionDescription": {
"message": "Enhance streaming video for language-learning."
},
"shortcutMineSubtitleDescription": {
"message": "Mine current subtitle. When video is synced without a subtitle file, starts/stops recording audio."
},
"shortcutMineSubtitleAndOpenDialogDescription": {
"message": "Mine current subtitle and open Anki export dialog. When video is synced without a subtitle file, starts/stops recording audio."
},
"shortcutUpdateLastCardDescription": {
"message": "Update last-created Anki card with asbplayer-captured media. When video is synced without a subtitle file, starts/stops recording audio."
},
"shortcutTakeScreenshotDescription": {
"message": "Manually take screenshot, overriding the one that is automatically taken when mining."
},
"shortcutToggleRecordingDescription": {
"message": "Manually start/stop audio recording, even when a subtitle file is loaded."
},
"shortcutSelectSubtitleTrackDescription": {
"message": "Select subtitle tracks to load."
},
"contextMenuMineSubtitle": {
"message": "Mine Subtitle"
},
"contextMenuLoadSubtitles": {
"message": "Load Subtitles"
}
}

29
asbplayer-extension/_locales/es/messages.json

@ -0,0 +1,29 @@
{
"extensionDescription": {
"message": "Mejora la transmisión de video para el aprendizaje de idiomas."
},
"contextMenuLoadSubtitles": {
"message": "Cargar Subtítulos"
},
"contextMenuMineSubtitle": {
"message": "Minar Subtítulos"
},
"shortcutMineSubtitleAndOpenDialogDescription": {
"message": "Minar subtítulo actual y abrir la pestaña para exportar a Anki. Cuando el video es sincronizado sin una pista de subtítulos, comienza/finaliza la grabación de audio."
},
"shortcutMineSubtitleDescription": {
"message": "Minar subtítulo actual. Cuando el video es sincronizado sin una pista de subtítulos, comienza/finaliza la grabación de audio."
},
"shortcutSelectSubtitleTrackDescription": {
"message": "Seleccionar subtítulos a cargar"
},
"shortcutTakeScreenshotDescription": {
"message": "Tomar captura de pantalla manualmente, sobrescribiendo la que se toma automáticamente al minar"
},
"shortcutToggleRecordingDescription": {
"message": "Comenzar/Finalizar grabación de audio manualmente, incluso cuando hay una pista de subtítulos cargada."
},
"shortcutUpdateLastCardDescription": {
"message": "Actualizar la última tarjeta de Anki creada con medios capturados por asbplayer. Cuando el video es sincronizado sin una pista de subtítulos, comienza/finaliza la grabación de audio."
}
}

29
asbplayer-extension/_locales/ja/messages.json

@ -0,0 +1,29 @@
{
"extensionDescription": {
"message": "言語学習のためにWeb上の動画を向上させる。"
},
"shortcutMineSubtitleAndOpenDialogDescription": {
"message": "現在の字幕をマイニングして Anki エクスポートウィンドウを開く。動画が字幕ファイルなしで同期されている場合、録音を開始/停止する。"
},
"shortcutMineSubtitleDescription": {
"message": "現在の字幕をマイニングする。動画が字幕ファイルなしで同期されている場合、録音を開始/停止する。"
},
"shortcutSelectSubtitleTrackDescription": {
"message": "ロードする字幕ファイルを選択する。"
},
"shortcutTakeScreenshotDescription": {
"message": "手動でスクリーンショットを撮影しマイニング時に自動的に撮影されたものを上書きする。"
},
"shortcutToggleRecordingDescription": {
"message": "字幕ファイルがロードされていても手動で録音を開始/終了する。"
},
"shortcutUpdateLastCardDescription": {
"message": "最後に作成した Anki カードに asbplayer でキャプチャしたメディアを添付して更新する。動画が字幕ファイルなしで同期されている場合、録音を開始/停止する。"
},
"contextMenuMineSubtitle": {
"message": "字幕をマイニングする"
},
"contextMenuLoadSubtitles": {
"message": "字幕ファイルをロードする"
}
}

23
asbplayer-extension/_locales/pl/messages.json

@ -0,0 +1,23 @@
{
"extensionDescription": {
"message": "Zsynchronizuj asbplayer ze strumieniowanym wideo"
},
"shortcutMineSubtitleAndOpenDialogDescription": {
"message": "Wykop bieżące napisy i otwórz okno eksportu Anki. Jeśli wideo jest zsynchronizowane bez pliku z napisami"
},
"shortcutMineSubtitleDescription": {
"message": "Wykop bieżące napisy. Jeśli wideo jest zsynchronizowane bez pliku z napisami"
},
"shortcutSelectSubtitleTrackDescription": {
"message": "Wybierz ścieżki napisów do załadowania."
},
"shortcutTakeScreenshotDescription": {
"message": "Manualnie wykonaj zrzut ekranu"
},
"shortcutToggleRecordingDescription": {
"message": "Manualnie rozpocznij/zatrzymaj nagrywanie audio"
},
"shortcutUpdateLastCardDescription": {
"message": "Zaktualizuj ostatnio utworzoną kartę Anki o media przechwycone przez asbplayer. Jeśli wideo jest zsynchronizowane bez pliku z napisami"
}
}

29
asbplayer-extension/_locales/pt_BR/messages.json

@ -0,0 +1,29 @@
{
"extensionDescription": {
"message": "Aprimora o streaming de vídeo para o aprendizado de idiomas."
},
"shortcutMineSubtitleAndOpenDialogDescription": {
"message": "Minera a legenda atual e abre a caixa de diálogo 'Exportar para o Anki'. Quando o vídeo está sincronizado sem um arquivo de legenda, inicia/para a gravação de áudio."
},
"shortcutMineSubtitleDescription": {
"message": "Minera a legenda atual. Quando o vídeo está sincronizado sem um arquivo de legenda, inicia/para a gravação de áudio."
},
"shortcutSelectSubtitleTrackDescription": {
"message": "Seleciona faixas de legenda para carregar"
},
"shortcutTakeScreenshotDescription": {
"message": "Tira manualmente uma captura de tela, substituindo aquela que é automaticamente capturada durante a mineração."
},
"shortcutToggleRecordingDescription": {
"message": "Inicia/para manualmente a gravação de áudio, mesmo quando um arquivo de legenda está carregado."
},
"shortcutUpdateLastCardDescription": {
"message": "Atualiza o último cartão criado no Anki com a mídia capturada pelo asbplayer. Quando o vídeo está sincronizado sem um arquivo de legenda, inicia/para a gravação de áudio."
},
"contextMenuLoadSubtitles": {
"message": "Carregar legenda"
},
"contextMenuMineSubtitle": {
"message": "Minerar legenda"
}
}

29
asbplayer-extension/_locales/zh_CN/messages.json

@ -0,0 +1,29 @@
{
"extensionDescription": {
"message": "将asbplayer与流媒体视频同步。"
},
"shortcutMineSubtitleAndOpenDialogDescription": {
"message": "挖掘当前字幕并打开Anki导出对话框。当视频在没有字幕文件的情况下同步时,开始/停止录制音频。"
},
"shortcutMineSubtitleDescription": {
"message": "挖掘当前字幕。当视频在没有字幕文件的情况下同步时,开始/停止录制音频。"
},
"shortcutSelectSubtitleTrackDescription": {
"message": "选择要加载的字幕轨道。"
},
"shortcutTakeScreenshotDescription": {
"message": "手动拍摄屏幕截图,覆盖挖掘时自动拍摄的屏幕截图。"
},
"shortcutToggleRecordingDescription": {
"message": "手动启动/停止音频录制,即使加载了字幕文件。"
},
"shortcutUpdateLastCardDescription": {
"message": "使用asbplayer捕获的媒体更新上次创建的Anki卡。当视频在没有字幕文件的情况下同步时,开始/停止录制音频。"
},
"contextMenuLoadSubtitles": {
"message": "加载字幕"
},
"contextMenuMineSubtitle": {
"message": "加载字幕"
}
}

2
asbplayer-extension/active-tab-permission-request-ui.js

File diff suppressed because one or more lines are too long

56
asbplayer-extension/active-tab-permission-request-ui.js.LICENSE.txt

@ -0,0 +1,56 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

2
asbplayer-extension/anki-ui.js

File diff suppressed because one or more lines are too long

77
asbplayer-extension/anki-ui.js.LICENSE.txt

@ -0,0 +1,77 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license Material-UI v4.11.2
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license Material-UI v4.12.1
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

293
asbplayer-extension/asbplayer-locales/de.json

@ -0,0 +1,293 @@
{
"action": {
"cancel": "Abbrechen",
"copy": "Kopieren",
"delete": "Löschen",
"downloadAudio": "Audio herunterladen",
"downloadImage": "Bild herunterladen",
"downloadSubtitlesAsSrt": "Untertitel als SRT herunterladen",
"jumpTo": "Springe zu",
"ok": "OK",
"mineSubtitle": "Mine Subtitle",
"openFiles": "Öffnen",
"loadSubtitles": "Load Subtitles",
"openApp": "Open App",
"openSidePanel": "Open Side Panel",
"mine": "Mine",
"updateLastCard": "Update Last Card",
"startRecording": "Start Recording",
"stopRecording": "Stop Recording",
"importSettings": "Import Settings",
"exportSettings": "Export Settings"
},
"postMineAction": {
"none": "None",
"showAnkiDialog": "Show Anki dialog",
"updateLastCard": "Update last card"
},
"ankiDialog": {
"applySelection": "Auswahl anwenden",
"audio": "Audio",
"audioFileLinkLost": "Audiodatei verloren aufgrund Seitenneuladens",
"cannotUpdateAudio": "Audiodatei bereits aufgenommen",
"copyToClipboard": "In Zwischenablage kopieren",
"definition": "Definition",
"export": "Exportieren",
"foundDuplicateNotes": "{{count}} Notizen mit Wort \"{{word}}\" in Feld \"{{field}}\" gefunden",
"foundNoDuplicateNote": "Nach Anki exportieren",
"image": "Bild",
"imageFileLinkLost": "Bilddatei verloren aufgrund Seitenneuladens",
"openInAnki": "In Anki öffnen",
"rerecord": "Neuaufnahme",
"resetSlider": "Zurücksetzen",
"rewind": "Zu Zeilenanfang",
"searchInAnki": "In Anki suchen",
"sentence": "Satz",
"source": "Quelle",
"tagList": "Kommaseparierte Liste von Schlagwörtern",
"title": "Anki Export",
"updateLastCard": "Zuletzt erstellte Karte aktualisieren",
"url": "URL",
"word": "Wort",
"zoomIn": "Hereinzoomen",
"zoomOut": "Herauszoomen"
},
"bar": {
"donate": "Spenden",
"help": "Hilfe",
"miningHistory": "Extraktions-Historie",
"settings": "Einstellungen",
"submitIssue": "Fehler melden"
},
"binds": {
"adjustOffset": "Untertiteloffset ±100ms",
"adjustOffsetToNextSubtitle": "Untertiteloffset nächster Zeile auf aktuellen Zeitstempel anpassen",
"adjustOffsetToPreviousSubtitle": "Untertiteloffset vorheriger Zeile auf aktuellen Zeitstempel anpassen",
"adjustOffsetToSubtitle": "Untertititeloffset anhand des aktuellen Zeitstempels setzen",
"adjustPlaybackRate": "Videogeschwindigkeit ±0",
"ankiExport": "Aktuellen Untertitel extrahieren und Anki-Dialog öffnen",
"copySubtitle": "Aktuellen Untertitel extrahieren",
"decreaseOffset": "Untertiteloffset -100ms",
"decreasePlaybackRate": "Videogeschwindigkeit -0",
"extensionAnkiDialog": "Aktuellen Untertitel extrahieren und Anki-Dialog öffnen. Audiorecorder starten / stoppen",
"extensionCopySubtitle": "Aktuellen Untertitel extrahieren. Audiorecorder starten / stoppen",
"extensionSelectSubtitleTrack": "Untertitelspuren auswählen",
"extensionTakeScreenshot": "Manuellen Screenshot erstellen - dieser überschreibt den automatisierten Screenshot",
"extensionToggleRecording": "Audiorecorder manuell starten / stoppen",
"extensionUpdateLastCard": "Zuletzt erstellte Anki-Karte mit aufgezeichnetem Untertitel",
"increaseOffset": "Untertiteloffset +100ms",
"increasePlaybackRate": "Videogeschwindigkeit +0",
"resetOffset": "Untertiteloffset zurücksetzen",
"seekBackward": "10 Sekunden zurück",
"seekBackwardOrForward": "10 Sekunden vorwärts / zurück",
"seekForward": "10 Sekunden vorwärts",
"seekToBeginningOfCurrentSubtitle": "Zum Anfang der aktuellen Zeile springen",
"seekToNextSubtitle": "Zu nächstem Untertitel springen",
"seekToPreviousSubtitle": "Zu vorherigem Untertitel springen",
"seekToSubtitle": "Zu vorherigem / nächsten Untertitel springen",
"takeScreenshot": "Screenshot erstellen",
"toggleAsbplayerSubtitleTrack1": "Untertitel 1 in absplayer umschalten",
"toggleAsbplayerSubtitleTrack2": "Untertitel 2 in asbplayer umschalten",
"toggleAsbplayerSubtitleTrack3": "Untertitel 3 in asbplayer umschalten",
"toggleAsbplayerSubtitleTracks": "Untertitel in absplayer umschalten",
"toggleAutoPause": "Auto-Pause aktivieren / deaktivieren",
"toggleCondensedPlayback": "Komprimiertes Audio-Playback aktivieren / deaktivieren",
"toggleFastForwardPlayback": "Toggle fast forward playback",
"togglePlay": "Play / Pause",
"toggleSubtitles": "Untertitel umschalten",
"toggleVideoSubtitleTrack1": "Untertitel 1 in Video umschalten",
"toggleVideoSubtitleTrack2": "Untertitel 2 in Video umschalten",
"toggleVideoSubtitleTrack3": "Untertitel 3 in Video umschalten",
"toggleVideoSubtitleTracks": "Untertitel in Video umschalten",
"updateLastCard": "Zuletzt erstellte Anki-Karte mit aufgezeichnetem Untertitel",
"toggleSidePanel": "Toggle side panel"
},
"controls": {
"autoPauseMode": "Auto-pause",
"condensedMode": "Condensed",
"fastForwardMode": "Fast-forward",
"normalMode": "Normal",
"playbackRate": "Playback Rate",
"subtitleOffset": "Subtitle Offset",
"subtitleAlignment": "Subtitle Alignment",
"toggleSubtitles": "Toggle Subtitles",
"playbackMode": "Playback Mode",
"unloadVideo": "Unload Video",
"selectAudioTrack": "Select Audio Track",
"selectVideoElement": "Select Video Element",
"popOut": "Pop Out",
"popIn": "Pop In",
"toggleFullscreen": "Toggle Fullscreen",
"toggleTheaterMode": "Toggle Theater Mode",
"showSubtitlePlayer": "Show Subtitle List",
"hideSubtitlePlayer": "Hide Subtitle List"
},
"copyHistory": {
"blank": "Leer",
"downloadMinedSubsAsSrt": "Extrahierte Untertitel als SRT herunterladen",
"exportToAnki": "Nach Anki exportieren",
"miningHistoryEmpty": "Keine Untertitel extrahiert"
},
"error": {
"bothAudioAndVideNotAllowed": "Cannot load both an audio and video file simultaneously",
"failedToLoadDirectory": "Failed to load directory",
"lostTabConnection": "Lost connection with tab: {{tabName}}",
"onlyOneAudioFile": "Es können nicht mehrere Audio-Dateien zeitgleich geöffnet werden",
"onlyOneDirectoryAllowed": "Cannot load more than one directory at a time",
"onlyOneVideoFile": "Es können nicht mehrere Videos zeitgleich geöffnet werden",
"subdirectoriesNotAllowed": "Cannot load a directory with subdirectories",
"subtitleFileNotOpen": "Subtitle file {{fileName}} is not open.",
"unknownExtension": "Dateityp von {{fileName}} konnte nicht erkannt werden",
"unsupportedExtension": "Nicht unterstützter Dateityp {{extension}}",
"videoPlayerDragAndDropNotAllowed": "Video player cannot receive dropped files. Drop outside of the video frame instead."
},
"extension": {
"settings": {
"asbplayerUrl": "absplayer-URL",
"autoLoadDetectedSubs": "Untertitel automatisch laden",
"cleanScreenshot": "Screenshot säubern",
"condensedPlaybackMinSkipInterval": "Maximale Stille zwischen gesprochenen Zeilen für komprimiertes Audio",
"cropScreenshot": "Screenshot zuschneiden",
"displaySubtitles": "Untertitel anzeigen",
"dragAndDrop": "Erlaube Untertitel Drag & Drop",
"subtitleListPreference": "Subtitle list preference",
"openSubtitleList": "Open subtitle list when loading subtitles",
"mining": "Extraktion",
"miningKeyboardShortcuts": "Tastaturkürzel für Extraktion",
"misc": "Sonstige",
"playback": "Playback",
"playbackKeyboardShortcuts": "Videosteuerung",
"recordAudio": "Audio aufnehmen",
"screenshotCaptureDelay": "Screenshot-Aufnahme-Delay",
"subtitles": "Untertitel",
"syncing": "Syncronisation",
"takeScreenshot": "Screenshot erstellen",
"updateAvailable": "Aktualisierung verfügbar"
},
"videoDataSync": {
"emptySubtitleTrack": "Empty",
"loadSubtitlesFirst": "Untertitel müssen ausgewählt werden",
"rememberTrackPreference": "Remember these track choices for this site",
"selectSubtitles": "Untertitel auswählen",
"subtitleTrack": "Untertitelspur",
"videoName": "Videotitel"
},
"videoSelect": {
"multipleVideoElements": "Mehrere Video-Elemente gefunden",
"selectVideo": "Wähle ein Video-Element zum synchronisieren aus",
"syncBeforeMine": "Ein Video muss mit absplayer synchronisiert werden",
"videoElement": "Video-Element"
},
"backgroundAudioRecordingPage": {
"description": "This page is used by asbplayer to capture audio."
}
},
"ftue": {
"welcome": "Welcome to asbplayer.",
"welcomeBody": "Check out the <0>readme</0> to see how to get started."
},
"info": {
"copiedSubtitle": "Copied: {{text}}",
"disabledAutoPause": "Auto-pause: Off",
"disabledCondensedPlayback": "Condensed playback: Off",
"disabledFastForwardPlayback": "Fast forward playback: Off",
"enabledAutoPause": "Auto-pause: On",
"enabledCondensedPlayback": "Condensed playback: On",
"enabledFastForwardPlayback": "Fast forward playback: On",
"exportedCard": "Exported card: {{result}}",
"playbackRate": "Playback Rate: {{rate}}",
"savedTimestamp": "Saved: {{timestamp}}",
"updatedCard": "Updated card: {{result}}",
"activeTabPermissionObtained": "Audio recording is now enabled for this tab."
},
"landing": {
"cta": "Untertitel und Medien hierher ziehen oder <1>suchen</1>",
"extensionNotInstalled": "Installiere die <1>Chrome-Erweiterung</1>",
"extensionUpdateAvailable": "Ein <1>Update</1> ist verfügbar",
"noSubtitles": "No subtitles",
"videoElementsDetected": "Load subtitles onto a video to start using asbplayer.",
"noVideoElementsDetected": "No videos detected."
},
"activeTabPermissionRequest": {
"title": "Enable audio recording",
"grantedTitle": "Audio recording enabled",
"prompt": "Click on the asbplayer action button in the top-right of the browser window to enable audio recording for this tab.",
"grantedPrompt": "Audio recording has been enabled for this tab. You can now begin mining."
},
"settings": {
"addCustomCss": "Add Custom CSS",
"addCustomField": "Eigenes Feld hinzufügen",
"anki": "Anki",
"ankiConnectUrl": "Anki-Connect-URL",
"audioField": "Audio-Feld",
"audioPaddingEnd": "Audio-Padding Ende",
"audioPaddingStart": "Audio-Padding Start",
"autoCopy": "Automatisch aktuellen Untertitel in Zwischenablage kopieren",
"autoPauseAtSubtitleEnd": "Am Ende des Untertitels",
"autoPauseAtSubtitleStart": "Am Anfang des Untertitels",
"autoPausePreference": "Auto-Pause",
"autoPausePreferenceHelperText": "Aktiviert keine Auto-Pause",
"fastForwardModePlaybackRate": "Fast-forward Mode Playback Rate",
"copyOnMine": "Extrahierte Untertitel in die Zwischenablage kopieren",
"corsHelperText": "Stelle sicher das {{origin}} in der webCorsOriginList innerhalb der AnkiConnect-Einstellungen steht (Siehe <0>video</0>).",
"customCssField": "CSS: {{styleKey}}",
"deck": "Stapel",
"definitionField": "Definitions-Feld",
"extensionOverriddenBind": "Überschrieben",
"extensionShortcut": "Durch Erweiterung gesetzt",
"imageBasedSubtitleScaleFactor": "Bildbasierte Untertitel-Skalierung",
"imageField": "Bild-Feld",
"keyboardShortcuts": "Tastatürkürzel",
"language": "Sprache",
"maxImageHeight": "Maximale Bild-Höhe",
"maxImageWidth": "Maximale Bild-Breite",
"mining": "Extraktion",
"miningHistoryStorageLimit": "Extraktions-Historie Speicherlimit",
"clickToMineDefaultAction": "Mining button default action",
"misc": "Sonstige",
"mp3Preference": "Audio in MP3 neu encoden (langsamer)",
"noteType": "Notiztyp",
"preCacheSubtitleDom": "Pre-cache Subtitle DOM",
"preCacheSubtitleDomHelperText": "If enabled, asbplayer will pre-render subtitle text elements in an offscreen document, and re-use those elements for subtitle display. This allows external code to persistently modify subtitle text before it is displayed.",
"recordingBind": "Aufnahme...",
"rememberSubtitleOffset": "Untertiteloffset merken",
"sentenceField": "Satz-Feld",
"streamingVideo": "Streaming Video",
"styleKey": "Style Key",
"styleValue": "Style Value",
"sourceField": "Quelle-Feld",
"subtitleAppearance": "Untertiteldarstellung",
"subtitleBackgroundColor": "Untertitelhintergrundfarbe",
"subtitleBackgroundOpacity": "Untertitelhintergrunddeckung",
"subtitleColor": "Untertitelfarbe",
"subtitleFontFamily": "Untertitelschriftart",
"subtitleOutlineColor": "Untertitelrandfarbe",
"subtitleOutlineThickness": "Untertitelrandbreite",
"subtitleShadowColor": "Subtitle Shadow Color",
"subtitleShadowThickness": "Subtitle Shadow Thickness",
"subtitleOutlineThicknessHelperText": "Adds an outline around subtitle text. If this causes overlapping lines, try using a different font.",
"subtitlePositionOffset": "Untertitelabstand vom unteren Bildschirmrand",
"subtitleAlignment": "Untertitel-Position",
"subtitleAlignmentBottom": "Unten",
"subtitleAlignmentTop": "Oben",
"subtitleRegexFilter": "Untertitelfilter (Regulärer Ausdruck)",
"subtitleRegexFilterTextReplacement": "Untertitelfilter Ersetzung",
"subtitleSize": "Untertitelgröße",
"subtitleThickness": "Subtitle Font Thickness",
"surroundingSubtitlesCountRadius": "Surrounding Subtitles Count Radius",
"surroundingSubtitlesTimeRadius": "Surrounding Subtitles Time Radius",
"tags": "Schlagwörter",
"tagsHelperText": "Kommaseparierte Liste von Schlagwörtern",
"theme": "Farbschema",
"themeDark": "Dunkel",
"themeLight": "Hell",
"title": "Einstellungen",
"unlockLocalFonts": "Click to unlock font menu",
"unboundBind": "Nicht gesetzt",
"urlField": "URL-Feld",
"wordField": "Wort-Feld"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Click, hold, and drag to mine multiple subtitles"
}
}

293
asbplayer-extension/asbplayer-locales/en.json

@ -0,0 +1,293 @@
{
"action": {
"cancel": "Cancel",
"copy": "Copy",
"delete": "Delete",
"downloadAudio": "Download Audio",
"downloadImage": "Download Image",
"downloadSubtitlesAsSrt": "Download Subtitles as SRT",
"jumpTo": "Jump To",
"ok": "OK",
"mineSubtitle": "Mine Subtitle",
"openFiles": "Open Files",
"loadSubtitles": "Load Subtitles",
"openApp": "Open App",
"openSidePanel": "Open Side Panel",
"mine": "Mine",
"updateLastCard": "Update Last Card",
"startRecording": "Start Recording",
"stopRecording": "Stop Recording",
"importSettings": "Import Settings",
"exportSettings": "Export Settings"
},
"postMineAction": {
"none": "None",
"showAnkiDialog": "Show Anki dialog",
"updateLastCard": "Update last card"
},
"ankiDialog": {
"applySelection": "Apply Selection",
"audio": "Audio",
"audioFileLinkLost": "Audio file link lost because of page reload",
"cannotUpdateAudio": "Audio clip cannot be updated because it is pre-recorded",
"copyToClipboard": "Copy to Clipboard",
"definition": "Definition",
"export": "Export",
"foundDuplicateNotes": "Found {{count}} notes with word \"{{word}}\" in field \"{{field}}\"",
"foundNoDuplicateNote": "No notes found with word \"{{word}}\" in field \"{{field}}\"",
"image": "Image",
"imageFileLinkLost": "Image file link lost because of page reload",
"openInAnki": "Open in Anki",
"rerecord": "Rerecord",
"resetSlider": "Reset",
"rewind": "Rewind",
"searchInAnki": "Search in Anki",
"sentence": "Sentence",
"source": "Source",
"tagList": "Comma-separated list of strings",
"title": "Anki Export",
"updateLastCard": "Update Last Card",
"url": "URL",
"word": "Word",
"zoomIn": "Zoom In",
"zoomOut": "Zoom Out"
},
"bar": {
"donate": "Donate",
"help": "Help",
"miningHistory": "Mining History",
"settings": "Settings",
"submitIssue": "Submit Issue"
},
"binds": {
"adjustOffset": "Adjust subtitle offset by ±100 ms",
"adjustOffsetToNextSubtitle": "Adjust subtitle offset so that next subtitle is at current timestamp",
"adjustOffsetToPreviousSubtitle": "Adjust subtitle offset so that previous subtitle is at current timestamp",
"adjustOffsetToSubtitle": "Adjust subtitle offset so that previous/next subtitle is at current timestamp",
"adjustPlaybackRate": "Adjust playback rate by ±0.1",
"ankiExport": "Mine current subtitle and open Anki dialog",
"copySubtitle": "Mine current subtitle",
"decreaseOffset": "Adjust subtitle offset by -100ms",
"decreasePlaybackRate": "Adjust playback rate by -0.1",
"extensionAnkiDialog": "Mine current subtitle and open Anki export dialog. When video is synced without a subtitle file, starts/stops recording audio.",
"extensionCopySubtitle": "Mine current subtitle. When video is synced without a subtitle file, starts/stops recording audio.",
"extensionSelectSubtitleTrack": "Select subtitle tracks to load.",
"extensionTakeScreenshot": "Manually take screenshot, overriding the one that is automatically taken when mining.",
"extensionToggleRecording": "Manually start/stop audio recording, even when a subtitle file is loaded.",
"extensionUpdateLastCard": "Update last-created Anki card with asbplayer-captured media. When video is synced without a subtitle file, starts/stops recording audio.",
"increaseOffset": "Adjust subtitle offset by +100ms",
"increasePlaybackRate": "Adjust playback rate by +0.1",
"resetOffset": "Reset subtitle offset",
"seekBackward": "Seek backward 10 seconds",
"seekBackwardOrForward": "Seek backward/forward 10 seconds",
"seekForward": "Seek forward 10 seconds",
"seekToBeginningOfCurrentSubtitle": "Seek to beginning of current subtitle",
"seekToNextSubtitle": "Seek to next subtitle",
"seekToPreviousSubtitle": "Seek to previous subtitle",
"seekToSubtitle": "Seek to previous/next subtitle",
"takeScreenshot": "Manually take screenshot, overriding the one that is automatically taken when mining",
"toggleAsbplayerSubtitleTrack1": "Toggle subtitle track 1 in asbplayer",
"toggleAsbplayerSubtitleTrack2": "Toggle subtitle track 2 in asbplayer",
"toggleAsbplayerSubtitleTrack3": "Toggle subtitle track 3 in asbplayer",
"toggleAsbplayerSubtitleTracks": "Toggle subtitle track in asbplayer",
"toggleAutoPause": "Toggle auto-pause",
"toggleCondensedPlayback": "Toggle condensed playback",
"toggleFastForwardPlayback": "Toggle fast forward playback",
"togglePlay": "Play/pause",
"toggleSubtitles": "Toggle subtitles",
"toggleVideoSubtitleTrack1": "Toggle subtitle track 1 in video",
"toggleVideoSubtitleTrack2": "Toggle subtitle track 2 in video",
"toggleVideoSubtitleTrack3": "Toggle subtitle track 3 in video",
"toggleVideoSubtitleTracks": "Toggle subtitle track in video",
"updateLastCard": "Update last-created Anki card with asbplayer-captured screenshot, audio, etc.",
"toggleSidePanel": "Toggle side panel"
},
"controls": {
"autoPauseMode": "Auto-pause",
"condensedMode": "Condensed",
"fastForwardMode": "Fast-forward",
"normalMode": "Normal",
"playbackRate": "Playback Rate",
"subtitleOffset": "Subtitle Offset",
"subtitleAlignment": "Subtitle Alignment",
"toggleSubtitles": "Toggle Subtitles",
"playbackMode": "Playback Mode",
"unloadVideo": "Unload Video",
"selectAudioTrack": "Select Audio Track",
"selectVideoElement": "Select Video Element",
"popOut": "Pop Out",
"popIn": "Pop In",
"toggleFullscreen": "Toggle Fullscreen",
"toggleTheaterMode": "Toggle Theater Mode",
"showSubtitlePlayer": "Show Subtitle List",
"hideSubtitlePlayer": "Hide Subtitle List"
},
"copyHistory": {
"blank": "Blank",
"downloadMinedSubsAsSrt": "Download Mined Subtitles as SRT",
"exportToAnki": "Export to Anki",
"miningHistoryEmpty": "Mining history is empty."
},
"error": {
"bothAudioAndVideNotAllowed": "Cannot load both an audio and video file simultaneously",
"failedToLoadDirectory": "Failed to load directory",
"lostTabConnection": "Lost connection with tab: {{tabName}}",
"onlyOneAudioFile": "Cannot open two audio files simultaneously",
"onlyOneDirectoryAllowed": "Cannot load more than one directory at a time",
"onlyOneVideoFile": "Cannot open two video files simultaneously",
"subdirectoriesNotAllowed": "Cannot load a directory with subdirectories",
"subtitleFileNotOpen": "Subtitle file {{fileName}} is not open.",
"unknownExtension": "Unable to determine extension of {{fileName}}",
"unsupportedExtension": "Unsupported extension {{extension}}",
"videoPlayerDragAndDropNotAllowed": "Video player cannot receive dropped files. Drop outside of the video frame instead."
},
"extension": {
"settings": {
"asbplayerUrl": "App URL",
"autoLoadDetectedSubs": "Auto-load detected subtitles",
"cleanScreenshot": "Clean screenshot",
"condensedPlaybackMinSkipInterval": "Condensed playback minimum skip interval",
"cropScreenshot": "Crop screenshot",
"displaySubtitles": "Display subtitles",
"dragAndDrop": "Allow subtitle file drag-and-drop",
"subtitleListPreference": "Subtitle list preference",
"openSubtitleList": "Open subtitle list when loading subtitles",
"mining": "Mining",
"miningKeyboardShortcuts": "Mining Keyboard Shortcuts",
"misc": "Misc",
"playback": "Playback",
"playbackKeyboardShortcuts": "Playback Keyboard Shortcuts",
"recordAudio": "Record audio",
"screenshotCaptureDelay": "Screenshot capture delay",
"subtitles": "Subtitles",
"syncing": "Syncing",
"takeScreenshot": "Take screenshot",
"updateAvailable": "Update Available"
},
"videoDataSync": {
"emptySubtitleTrack": "Empty",
"loadSubtitlesFirst": "Subtitles must be loaded before you can start mining.",
"rememberTrackPreference": "Remember these track choices for this site",
"selectSubtitles": "Select Subtitles",
"subtitleTrack": "Subtitle Track",
"videoName": "Video Name"
},
"videoSelect": {
"multipleVideoElements": "Multiple Video Elements Detected",
"selectVideo": "Select a video element to sync it with asbplayer.",
"syncBeforeMine": "A video element must be synced with asbplayer before it can be mined. Select a video element to sync it with asbplayer.",
"videoElement": "Video Element"
},
"backgroundAudioRecordingPage": {
"description": "This page is used by asbplayer to capture audio."
}
},
"ftue": {
"welcome": "Welcome to asbplayer.",
"welcomeBody": "Check out the <0>readme</0> to see how to get started."
},
"info": {
"copiedSubtitle": "Copied: {{text}}",
"disabledAutoPause": "Auto-pause: Off",
"disabledCondensedPlayback": "Condensed playback: Off",
"disabledFastForwardPlayback": "Fast forward playback: Off",
"enabledAutoPause": "Auto-pause: On",
"enabledCondensedPlayback": "Condensed playback: On",
"enabledFastForwardPlayback": "Fast forward playback: On",
"exportedCard": "Exported card: {{result}}",
"playbackRate": "Playback Rate: {{rate}}",
"savedTimestamp": "Saved: {{timestamp}}",
"updatedCard": "Updated card: {{result}}",
"activeTabPermissionObtained": "Audio recording is now enabled for this tab."
},
"landing": {
"cta": "Drag and drop subtitle and media files, or <1>browse</1>.",
"extensionNotInstalled": "Install the <1>Chrome extension</1> to sync subtitles with streaming video.",
"extensionUpdateAvailable": "An extension <1>update</1> is available.",
"noSubtitles": "No subtitles",
"videoElementsDetected": "Load subtitles onto a video to start using asbplayer.",
"noVideoElementsDetected": "No videos detected."
},
"activeTabPermissionRequest": {
"title": "Enable audio recording",
"grantedTitle": "Audio recording enabled",
"prompt": "Click on the asbplayer action button in the top-right of the browser window to enable audio recording for this tab.",
"grantedPrompt": "Audio recording has been enabled for this tab. You can now begin mining."
},
"settings": {
"addCustomCss": "Add Custom CSS",
"addCustomField": "Add Custom Field",
"anki": "Anki",
"ankiConnectUrl": "Anki Connect URL",
"audioField": "Audio Field",
"audioPaddingEnd": "Audio Padding End",
"audioPaddingStart": "Audio Padding Start",
"autoCopy": "Auto-copy current subtitle to clipboard",
"autoPauseAtSubtitleEnd": "At Subtitle End",
"autoPauseAtSubtitleStart": "At Subtitle Start",
"autoPausePreference": "Auto-pause Preference",
"autoPausePreferenceHelperText": "Does not enable auto-pause. Sets the preference for when to pause when auto-pause is enabled.",
"fastForwardModePlaybackRate": "Fast-forward Mode Playback Rate",
"copyOnMine": "Copy mined subtitles to clipboard",
"corsHelperText": "Ensure that {{origin}} is in the webCorsOriginList in your AnkiConnect settings as in this <0>video</0>.",
"customCssField": "CSS: {{styleKey}}",
"deck": "Deck",
"definitionField": "Definition Field",
"extensionOverriddenBind": "Overridden",
"extensionShortcut": "Extension shortcut",
"imageBasedSubtitleScaleFactor": "Image-based Subtitle Scale Factor",
"imageField": "Image Field",
"keyboardShortcuts": "Keyboard Shortcuts",
"language": "Language",
"maxImageHeight": "Max Image Height",
"maxImageWidth": "Max Image Width",
"mining": "Mining",
"miningHistoryStorageLimit": "Mining history storage limit",
"clickToMineDefaultAction": "Mining button default action",
"misc": "Misc",
"mp3Preference": "Re-encode audio as mp3 (slower)",
"noteType": "Note Type",
"preCacheSubtitleDom": "Pre-cache Subtitle DOM",
"preCacheSubtitleDomHelperText": "If enabled, asbplayer will pre-render subtitle text elements in an offscreen element, and re-use those elements for subtitle display. This allows external code to persistently modify subtitle text before it is displayed.",
"recordingBind": "Recording",
"rememberSubtitleOffset": "Remember subtitle offset",
"sentenceField": "Sentence Field",
"streamingVideo": "Streaming Video",
"styleKey": "Style Key",
"styleValue": "Style Value",
"sourceField": "Source Field",
"subtitleAppearance": "Subtitle Appearance",
"subtitleBackgroundColor": "Subtitle Background Color",
"subtitleBackgroundOpacity": "Subtitle Background Opacity",
"subtitleColor": "Subtitle Color",
"subtitleFontFamily": "Subtitle Font Family",
"subtitleOutlineColor": "Subtitle Outline Color",
"subtitleOutlineThickness": "Subtitle Outline Thickness",
"subtitleShadowColor": "Subtitle Shadow Color",
"subtitleShadowThickness": "Subtitle Shadow Thickness",
"subtitleOutlineThicknessHelperText": "Adds an outline around subtitle text. If this causes overlapping lines, try using a different font.",
"subtitlePositionOffset": "Subtitle position offset from bottom",
"subtitleAlignment": "Subtitle Alignment",
"subtitleAlignmentBottom": "Bottom",
"subtitleAlignmentTop": "Top",
"subtitleRegexFilter": "Subtitle regex filter",
"subtitleRegexFilterTextReplacement": "Subtitle regex filter text replacement",
"subtitleSize": "Subtitle Size",
"subtitleThickness": "Subtitle Font Thickness",
"surroundingSubtitlesCountRadius": "Surrounding Subtitles Count Radius",
"surroundingSubtitlesTimeRadius": "Surrounding Subtitles Time Radius",
"tags": "Tags",
"tagsHelperText": "Comma-separated list of strings",
"theme": "Theme",
"themeDark": "Dark",
"themeLight": "Light",
"title": "Settings",
"unlockLocalFonts": "Click to unlock font menu",
"unboundBind": "Unbound",
"urlField": "URL Field",
"wordField": "Word Field"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Click, hold, and drag to mine multiple subtitles"
}
}

294
asbplayer-extension/asbplayer-locales/es.json

@ -0,0 +1,294 @@
{
"action": {
"cancel": "Cancelar",
"copy": "Copiar",
"delete": "Borrar",
"downloadAudio": "Descargar Audio",
"downloadImage": "Descargar Imagen",
"downloadSubtitlesAsSrt": "Descargar Subtítulos como SRT",
"exportSettings": "Exportar Ajustes",
"importSettings": "Importar Ajustes",
"jumpTo": "Saltar A",
"loadSubtitles": "Cargar Subtítulos",
"mine": "Minar",
"mineSubtitle": "Minar Subtítulo",
"ok": "OK",
"openApp": "Abrir App",
"openFiles": "Abrir Archivos",
"openSidePanel": "Abrir Panel Lateral",
"startRecording": "Comenzar Grabación",
"stopRecording": "Finalizar Grabación",
"updateLastCard": "Actualizar Última Tarjeta"
},
"activeTabPermissionRequest": {
"grantedPrompt": "Grabación de audio habilitada para esta pestaña. Puedes empezar a minar.",
"grantedTitle": "Grabación de audio habilitada",
"prompt": "Haz click en el botón de acción de asbplayer en la esquina superior derecha de la ventana del navegador para habilitar la grabación de audio para esta pestaña.",
"title": "Habilitar grabación de audio"
},
"ankiDialog": {
"applySelection": "Aplicar Selección",
"audio": "Audio",
"audioFileLinkLost": "Se perdió el link al archivo de audio al recargar la página",
"cannotUpdateAudio": "El clip de audio no puede ser actualizado porque ya ha sido grabado",
"copyToClipboard": "Copiar al Portapapeles",
"definition": "Definición",
"export": "Exportar",
"foundDuplicateNotes": "Se encontraron {{count}} tarjetas con la palabra \"{{word}}\" en el campo \"{{field}}\"",
"foundNoDuplicateNote": "No se encontraron tarjetas con la palabra \"{{word}}\" en el campo \"{{field}}\"",
"image": "Imagen",
"imageFileLinkLost": "Se perdió el link a la imagen al recargar la página",
"openInAnki": "Abrir en Anki",
"rerecord": "Regrabar",
"resetSlider": "Reestablecer",
"rewind": "Retroceder",
"searchInAnki": "Buscar en Anki",
"sentence": "Oración",
"source": "Fuente",
"tagList": "Lista de strings separados por coma",
"title": "Exportar a Anki",
"updateLastCard": "Actualizar Última Tarjeta",
"url": "URL",
"word": "Palabra",
"zoomIn": "Aumentar Zoom",
"zoomOut": "Reducir Zoom"
},
"bar": {
"donate": "Donar",
"help": "Ayuda",
"miningHistory": "Historial de Minado",
"settings": "Ajustes",
"submitIssue": "Reportar Problema"
},
"binds": {
"adjustOffset": "Ajustar offset de los subtítulos en ±100 ms",
"adjustOffsetToNextSubtitle": "Ajustar offset de los subtítulos para que el siguiente subtítulo esté en el momento actual",
"adjustOffsetToPreviousSubtitle": "Ajustar offset de los subtítulos para que el subtítulo anterior esté en el momento actual",
"adjustOffsetToSubtitle": "Ajustar offset de los subtítulos para que el subtítulo anterior/siguiente esté en el momento actual",
"adjustPlaybackRate": "Ajustar velocidad de reproducción en ±0.1",
"ankiExport": "Minar subtítulo actual y abrir ventana de Anki",
"copySubtitle": "Minar subtítulo actual",
"decreaseOffset": "Ajustar offset de los subtítulos en -100 ms",
"decreasePlaybackRate": "Ajustar velocidad de reproducción en -0.1",
"extensionAnkiDialog": "Minar subtítulo actual y abrir ventana de Anki. Cuando el video es sincronizado sin un archivo de subtítulos, comienza/finaliza la grabación de audio.",
"extensionCopySubtitle": "Minar subtítulo actual. Cuando el video es sincronizado sin un archivo de subtítulos, comienza/finaliza la grabación de audio.",
"extensionSelectSubtitleTrack": "Seleccionar pista de subtítulos a cargar",
"extensionTakeScreenshot": "Tomar captura de pantalla manualmente, sobrescribiendo la que es tomada automáticamente",
"extensionToggleRecording": "Comenzar/Finalizar manualmente la grabación de audio, incluso cuando hay una pista de subtítulos cargada",
"extensionUpdateLastCard": "Actualizar la última tarjeta de Anki creada con medios capturados por asbplayer. Cuando el video es sincronizado sin una pista de subtítulos, comienza/finaliza la grabación de audio.",
"increaseOffset": "Ajustar offset de los subtítulos en +100ms",
"increasePlaybackRate": "Ajustar velocidad de reproducción en +0.1",
"resetOffset": "Reestablecer offset de los subtítulos",
"seekBackward": "Retroceder 10 segundos",
"seekBackwardOrForward": "Avanzar/Retroceder 10 segundos",
"seekForward": "Avanzar 10 segundos",
"seekToBeginningOfCurrentSubtitle": "Ir al inicio del subtítulo actual",
"seekToNextSubtitle": "Avanzar al siguiente subtítulo",
"seekToPreviousSubtitle": "Retroceder al subtítulo anterior",
"seekToSubtitle": "Ir al subtítulo anterior/siguiente",
"takeScreenshot": "Tomar captura de pantalla manualmente, sobrescribiendo la que es tomada automáticamente",
"toggleAsbplayerSubtitleTrack1": "Activar/Desactivar pista de subtítulos 1 en asbplayer",
"toggleAsbplayerSubtitleTrack2": "Activar/Desactivar pista de subtítulos 2 en asbplayer",
"toggleAsbplayerSubtitleTrack3": "Activar/Desactivar pista de subtítulos 3 en asbplayer",
"toggleAsbplayerSubtitleTracks": "Activar/Desactivar pista de subtítulos en asbplayer",
"toggleAutoPause": "Activar/Desactivar pausado automático",
"toggleCondensedPlayback": "Activar/Desactivar reproducción condensada",
"toggleFastForwardPlayback": "Activar/Desactivar reproducción acelerada",
"togglePlay": "Reproducir/Pausar",
"toggleSidePanel": "Abrir/Cerrar Panel Lateral",
"toggleSubtitles": "Activar/Desactivar subtítulos",
"toggleVideoSubtitleTrack1": "Activar/Desactivar pista de subtítulos 1 en el video",
"toggleVideoSubtitleTrack2": "Activar/Desactivar pista de subtítulos 2 en el video",
"toggleVideoSubtitleTrack3": "Activar/Desactivar pista de subtítulos 3 en el video",
"toggleVideoSubtitleTracks": "Activar/Desactivar pista de subtítulos en el video",
"updateLastCard": "Actualizar la última tarjeta de Anki creada con captura de pantalla, audio, etc. capturado por asbplayer"
},
"controls": {
"autoPauseMode": "Pausado Automático",
"condensedMode": "Condensado",
"fastForwardMode": "Acelerado",
"hideSubtitlePlayer": "Ocultar Lista de Subtítulos",
"normalMode": "Normal",
"playbackMode": "Modo de Reproducción",
"playbackRate": "Velocidad de Reproducción",
"popIn": "Volver a la Aplicación",
"popOut": "Abrir en Otra Ventana",
"selectAudioTrack": "Seleccionar Pista de Audio",
"selectVideoElement": "Seleccionar Elemento de Video",
"showSubtitlePlayer": "Mostrar Lista de Subtítulos",
"subtitleAlignment": "Alineación de Subtítulos",
"subtitleOffset": "Offset de Subtítulos",
"toggleFullscreen": "Pantalla Completa",
"toggleSubtitles": "Activar/Desactivar Subtítulos",
"toggleTheaterMode": "Modo Cine",
"unloadVideo": "Remover Video"
},
"copyHistory": {
"blank": "En Blanco",
"downloadMinedSubsAsSrt": "Descargar Subtítulos minados como SRT",
"exportToAnki": "Exportar a Anki",
"miningHistoryEmpty": "El historial de minado está vacío."
},
"error": {
"bothAudioAndVideNotAllowed": "No pueden cargarse archivos de audio y video simultáneamente",
"failedToLoadDirectory": "Error al cargar directorio",
"lostTabConnection": "Se perdió la conexión con la pestaña: {{tabName}}",
"onlyOneAudioFile": "No pueden abrirse dos archivos de audio simultáneamente",
"onlyOneDirectoryAllowed": "No puede cargarse más de un directorio a la vez",
"onlyOneVideoFile": "No pueden abrirse dos archivos de video simultáneamente",
"subdirectoriesNotAllowed": "No puede cargarse un directorio que contenga subdirectorios",
"subtitleFileNotOpen": "La pista de subtítulos {{fileName}} no está abierta",
"unknownExtension": "No pudo determinarse la extensión de {{fileName}}",
"unsupportedExtension": "Extensión no soportada {{extension}}",
"videoPlayerDragAndDropNotAllowed": "El reproductor de video no puede recibir archivos. Arrástralos fuera del cuadro de video."
},
"extension": {
"backgroundAudioRecordingPage": {
"description": "Esta página es usada por asbplayer para capturar audio"
},
"settings": {
"asbplayerUrl": "URL de la Aplicación",
"autoLoadDetectedSubs": "Cargar subtítulos detectados automáticamente",
"cleanScreenshot": "Limpiar captura de pantalla",
"condensedPlaybackMinSkipInterval": "Intervalo mínimo de salto para reproducción condensada",
"cropScreenshot": "Recortar captura de pantalla",
"displaySubtitles": "Mostrar subtítulos",
"dragAndDrop": "Permitir arrastrar y soltar archivos de subtítulos",
"mining": "Minado",
"miningKeyboardShortcuts": "Atajos de Teclado para Minado",
"misc": "Otros",
"openSubtitleList": "Abrir lista de subtítulos al cargar subtítulos",
"playback": "Reproducción",
"playbackKeyboardShortcuts": "Atajos de Teclado para Reproducción",
"recordAudio": "Grabar audio",
"screenshotCaptureDelay": "Retardo de captura de pantalla",
"subtitleListPreference": "Preferencia de lista de subtítulos",
"subtitles": "Subtítulos",
"syncing": "Sincronización",
"takeScreenshot": "Tomar captura de pantalla",
"updateAvailable": "Actualización Disponible"
},
"videoDataSync": {
"emptySubtitleTrack": "En Blanco",
"loadSubtitlesFirst": "Deben cargarse los subtítulos antes de comenzar a minar",
"rememberTrackPreference": "Recordar estas opciones de pista para este sitio",
"selectSubtitles": "Seleccionar Subtítulos",
"subtitleTrack": "Pista de Subtítulos",
"videoName": "Nombre de Video"
},
"videoSelect": {
"multipleVideoElements": "Múltiples Elementos de Video Detectados",
"selectVideo": "Selecciona un elemento de video para sincronizar con asbplayer.",
"syncBeforeMine": "Un elemento de video debe ser sincronizado con asbplayer antes de que pueda ser minado. Selecciona un elemento de video a sincronizar con asbplayer.",
"videoElement": "Elemento de Video"
}
},
"ftue": {
"welcome": "Bienvenido a asbplayer",
"welcomeBody": "Revisa el <0>léeme</0> para comenzar\ninfo.activeTabPermissionObtained,Grabación de audio activada para esta pestaña"
},
"info": {
"activeTabPermissionObtained": "Grabación de audio activada para esta pestaña",
"copiedSubtitle": "Copiado: {{text}}",
"disabledAutoPause": "Pausado automático: Desactivado",
"disabledCondensedPlayback": "Reproducción condensada: Desactivada",
"disabledFastForwardPlayback": "Reproducción acelerada: Desactivada",
"enabledAutoPause": "Pausado automático: Activado",
"enabledCondensedPlayback": "Reproducción condensada: Activada",
"enabledFastForwardPlayback": "Reproducción acelerada: Activada",
"exportedCard": "Tarjeta exportada: {{result}}",
"playbackRate": "Velocidad de Reproducción: {{rate}}",
"savedTimestamp": "Guardado: {{timestamp}}",
"updatedCard": "Tarjeta actualizada: {{result}}"
},
"landing": {
"cta": "Arrastra archivos de medios y subtítulos o <1>explora</1>.",
"extensionNotInstalled": "Instala la <1>extensión de Chrome</1> para sincronizar los subtítulos con el video.",
"extensionUpdateAvailable": "Hay una <1>actualización</1> disponible para la extensión.",
"noSubtitles": "No hay subtítulos",
"noVideoElementsDetected": "No se detectaron videos",
"videoElementsDetected": "Carga subtítulos a un video para comenzar a usar asbplayer"
},
"postMineAction": {
"none": "Ninguna",
"showAnkiDialog": "Mostrar ventana de Anki",
"updateLastCard": "Actualizar última tarjeta"
},
"settings": {
"addCustomCss": "Agregar CSS Personalizado",
"addCustomField": "Agregar Campo Personalizado",
"anki": "Anki",
"ankiConnectUrl": "URL de Anki Connect",
"audioField": "Campo de Audio",
"audioPaddingEnd": "Retraso del final de la grabación de audio",
"audioPaddingStart": "Adelanto del inicio de la grabación de audio",
"autoCopy": "Copiar automáticamente el subtítulo actual al portapapeles",
"autoPauseAtSubtitleEnd": "Al Final del Subtítulo",
"autoPauseAtSubtitleStart": "Al Inicio del Subtítulo",
"autoPausePreference": "Preferencia para el pausado automático",
"autoPausePreferenceHelperText": "No activa el pausado automático. Establece cuando pausar si el pausado automático está activado.",
"clickToMineDefaultAction": "Acción por defecto del botón de minado",
"copyOnMine": "Copiar subtítulos minados al portapapeles",
"corsHelperText": "Asegúrate de que {{origin}} esté en webCorsOriginList en tu configuración de AnkiConnect como en este <0>video</0>.",
"customCssField": "CSS: {{styleKey}}",
"deck": "Mazo",
"definitionField": "Campo de Definición",
"extensionOverriddenBind": "Anulado",
"extensionShortcut": "Atajo de teclado de la extensión",
"fastForwardModePlaybackRate": "Velocidad de la Reproducción Acelerada",
"imageBasedSubtitleScaleFactor": "Factor de Escalado para Subtítulos Basados en Imágenes",
"imageField": "Campo de Imagen",
"keyboardShortcuts": "Atajos de Teclado",
"language": "Idioma",
"maxImageHeight": "Altura máxima de la imagen",
"maxImageWidth": "Ancho máximo de la imagen",
"mining": "Minado",
"miningHistoryStorageLimit": "Límite de almacenamiento del historial de minado",
"misc": "Otros",
"mp3Preference": "Recodificar audio como MP3 (más lento)",
"noteType": "Tipo de Nota",
"preCacheSubtitleDom": "Precargar DOM de Subtítulos",
"preCacheSubtitleDomHelperText": "Si está activado, asbplayer renderizará los elementos de texto del subtítulo en un elemento fuera de pantalla, y reusará estos elementos para mostrar los subtítulos. Esto permite a código externo modifique persistentemente el texto del subtítulo antes de que se muestre.",
"recordingBind": "Grabando",
"rememberSubtitleOffset": "Recordar offset de subtítulos",
"sentenceField": "Campo de Oración",
"sourceField": "Campo de Fuente",
"streamingVideo": "Streaming de Video",
"styleKey": "Tecla de Estilo",
"styleValue": "Valor de Estilo",
"subtitleAlignment": "Alineación de Subtítulos",
"subtitleAlignmentBottom": "Inferior",
"subtitleAlignmentTop": "Superior",
"subtitleAppearance": "Apariencia de Subtítulos",
"subtitleBackgroundColor": "Color del Fondo de los Subtítulos",
"subtitleBackgroundOpacity": "Opacidad del Fondo de los Subtítulos",
"subtitleColor": "Color de los Subtítulos",
"subtitleFontFamily": "Familia de Fuente de los Subtítulos",
"subtitleOutlineColor": "Color del Contorno de los Subtítulos",
"subtitleOutlineThickness": "Grosor del Contorno de los Subtítulos",
"subtitleOutlineThicknessHelperText": "Agrega un contorno al texto de los subtítulos. Si esto causa líneas superpuestas, trata de usar otra fuente.",
"subtitlePositionOffset": "Distancia de los subtítulos desde el borde inferior",
"subtitleRegexFilter": "Filtro regex para subtítulos",
"subtitleRegexFilterTextReplacement": "Texto de reemplazo para el filtro regex",
"subtitleShadowColor": "Color de la Sombra de los Subtítulos",
"subtitleShadowThickness": "Grosor del Sombreado de los Subtítulos",
"subtitleSize": "Tamaño de los subtítulos",
"subtitleThickness": "Grosor de la Fuente de los Subtítulos",
"surroundingSubtitlesCountRadius": "Radio de Cantidad de Subtítulos Circundantes",
"surroundingSubtitlesTimeRadius": "Radio Temporal para Subtítulos Circundantes",
"tags": "Etiquetas",
"tagsHelperText": "Lista de strings separados por coma",
"theme": "Tema",
"themeDark": "Oscuro",
"themeLight": "Claro",
"title": "Ajustes",
"unboundBind": "Sin Asignar",
"unlockLocalFonts": "Haz click para desbloquear el menú de fuentes",
"urlField": "Campo de URL",
"wordField": "Campo de Palabra"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Haz click, mantén y arrastra para minar múltiples subtítulos"
}
}

293
asbplayer-extension/asbplayer-locales/ja.json

@ -0,0 +1,293 @@
{
"action": {
"cancel": "キャンセル",
"copy": "コピー",
"delete": "削除",
"downloadAudio": "音声をダウンロード",
"downloadImage": "画像をダウンロード",
"downloadSubtitlesAsSrt": "SRT 形式字幕をダウンロード",
"jumpTo": "ジャンプ",
"ok": "OK",
"mineSubtitle": "字幕をマイニングする",
"openFiles": "開く",
"loadSubtitles": "字幕をロードする",
"openApp": "アプリを開く",
"openSidePanel": "サイドパネルを開く",
"mine": "マイニングする",
"updateLastCard": "最後のカードを更新する",
"startRecording": "録音開始",
"stopRecording": "録音停止",
"importSettings": "設定をインポートする",
"exportSettings": "設定をエクスポートする"
},
"postMineAction": {
"none": "何もしない",
"showAnkiDialog": "Anki のエクスポートウィンドウを開く",
"updateLastCard": "最後のカードを更新する"
},
"ankiDialog": {
"applySelection": "選択範囲を適用する",
"audio": "音声",
"audioFileLinkLost": "ブラウザページを更新したため、音声ファイルの参照先が失われました",
"cannotUpdateAudio": "事前に録音されたため、音声クリップを更新できません",
"copyToClipboard": "クリップボードにコピー",
"definition": "詳細",
"export": "エクスポート",
"foundDuplicateNotes": "フィールド「{{field}}」に単語「{{word}}」 が含まれるメモが {{count}} 件見つかりました",
"foundNoDuplicateNote": "フィールド「{{field}}」に単語「{{word}}」 が含まれるメモはありません",
"image": "画像",
"imageFileLinkLost": "ブラウザページを更新したため、画像ファイルの参照先が失われました",
"openInAnki": "Anki で開く",
"rerecord": "再録音",
"resetSlider": "リセット",
"rewind": "巻き戻し",
"searchInAnki": "Anki で検索する",
"sentence": "文",
"source": "ソース",
"tagList": "テキストのリスト(カンマ「,」区切り)",
"title": "Anki エクスポート",
"updateLastCard": "最後のカードを更新する",
"url": "URL",
"word": "単語",
"zoomIn": "ズームイン",
"zoomOut": "ズームアウト"
},
"bar": {
"donate": "寄付",
"help": "ヘルプ",
"miningHistory": "マイニング履歴",
"settings": "設定",
"submitIssue": "不具合の報告"
},
"binds": {
"adjustOffset": "字幕の表示タイミング ±100ms",
"adjustOffsetToNextSubtitle": "次の字幕を現在のタイムスタンプに合わせる",
"adjustOffsetToPreviousSubtitle": "前の字幕を現在のタイムスタンプに合わせる",
"adjustOffsetToSubtitle": "前/次の字幕を現在のタイムスタンプに合わせる",
"adjustPlaybackRate": "再生速度 ±0.1",
"ankiExport": "現在の字幕をマイニングし、Anki のエクスポートウィンドウを開く",
"copySubtitle": "現在の字幕をマイニング",
"decreaseOffset": "字幕の表示タイミング -100ms",
"decreasePlaybackRate": "再生速度 -0.1",
"extensionAnkiDialog": "現在の字幕をマイニングして Anki のエクスポートウィンドウを開く。動画が字幕ファイルなしで同期されている場合、録音を開始/停止する。",
"extensionCopySubtitle": "現在の字幕をマイニングする。動画が字幕ファイルなしで同期されている場合、録音を開始/停止する。",
"extensionSelectSubtitleTrack": "ロードする字幕ファイルを選択する。",
"extensionTakeScreenshot": "手動でスクリーンショットを撮影しマイニング時に自動的に撮影されたものを上書きする。",
"extensionToggleRecording": "字幕ファイルがロードされていても手動で録音を開始/終了する。",
"extensionUpdateLastCard": "最後に作成した Anki カードに asbplayer でキャプチャしたメディアを添付して更新する。動画が字幕ファイルなしで同期されている場合、録音を開始/停止する。",
"increaseOffset": "字幕の表示タイミング +100ms",
"increasePlaybackRate": "再生速度 +0.1",
"resetOffset": "字幕の表示タイミングをリセット",
"seekBackward": "10 秒巻き戻し",
"seekBackwardOrForward": "10 秒巻き戻し/早送り",
"seekForward": "10 秒早送り",
"seekToBeginningOfCurrentSubtitle": "今の字幕冒頭に移動",
"seekToNextSubtitle": "次の字幕に早送り",
"seekToPreviousSubtitle": "前の字幕に巻き戻り",
"seekToSubtitle": "前/次の字幕に移動",
"takeScreenshot": "手動でスクリーンショットを撮影しマイニング時に自動的に撮影されたものを上書きする",
"toggleAsbplayerSubtitleTrack1": "asbplayer の字幕トラック 1 オン/オフ",
"toggleAsbplayerSubtitleTrack2": "asbplayer の字幕トラック 2 オン/オフ",
"toggleAsbplayerSubtitleTrack3": "asbplayer の字幕トラック 3 オン/オフ",
"toggleAsbplayerSubtitleTracks": "asbplayer の字幕トラック オン/オフ",
"toggleAutoPause": "自動一時停止オン/オフ",
"toggleCondensedPlayback": "短縮プレイバック",
"toggleFastForwardPlayback": "早送りプレイバックオン/オフ",
"togglePlay": "再生/一時停止",
"toggleSubtitles": "字幕オン/オフ",
"toggleVideoSubtitleTrack1": "動画の字幕トラック 1 オン/オフ",
"toggleVideoSubtitleTrack2": "動画の字幕トラック 2 オン/オフ",
"toggleVideoSubtitleTrack3": "動画の字幕トラック 3 オン/オフ",
"toggleVideoSubtitleTracks": "動画の字幕トラック オン/オフ",
"updateLastCard": "asbplayer でキャプチャしたスクリーンショットや音声を、最後に作成した Anki カードに添付して更新する",
"toggleSidePanel": "サイドパネルを開く/閉じる"
},
"controls": {
"autoPauseMode": "自動一時停止",
"condensedMode": "短縮",
"fastForwardMode": "早送り",
"normalMode": "通常",
"playbackRate": "再生速度",
"subtitleOffset": "字幕表示タイミング",
"subtitleAlignment": "字幕の表示位置",
"toggleSubtitles": "字幕オン/オフ",
"playbackMode": "プレイバックモード",
"unloadVideo": "動画をアンロード",
"selectAudioTrack": "オーディオトラックを選択",
"selectVideoElement": "動画埋め込み要素",
"popOut": "動画をポップアウト",
"popIn": "動画をポップイン",
"toggleFullscreen": "フルスクリーンオン/オフ",
"toggleTheaterMode": "シアターモードオン/オフ",
"showSubtitlePlayer": "字幕リストを表示",
"hideSubtitlePlayer": "字幕リストを非表示"
},
"copyHistory": {
"blank": "空白",
"downloadMinedSubsAsSrt": "マイニングした字幕を SRT 形式でダウンロードする",
"exportToAnki": "Anki にエクスポートする",
"miningHistoryEmpty": "マイニング履歴はありませïん"
},
"error": {
"bothAudioAndVideNotAllowed": "音声と動画ファイルを同時にロードできません",
"failedToLoadDirectory": "ディレクトリのロードに失敗しました",
"lostTabConnection": "タブ「{{tabName}}」への接続が失われました",
"onlyOneAudioFile": "同時に複数の音声ファイルを開けません",
"onlyOneDirectoryAllowed": "一度に複数のディレクトリをロードできません",
"onlyOneVideoFile": "同時に複数の動画ファイルを開けません",
"subdirectoriesNotAllowed": "サブディレクトリのあるディレクトリはロードできません",
"subtitleFileNotOpen": "字幕ファイル「{{fileName}} 」が開いていません",
"unknownExtension": "{{fileName}}の拡張子を確認できません",
"unsupportedExtension": "対応していない拡張子です:{{extension}}",
"videoPlayerDragAndDropNotAllowed": "動画プレイヤーはドロップしたファイルを受け取れません。動画のフレーム外にファイルをドロップしてください。"
},
"extension": {
"settings": {
"asbplayerUrl": "アプリのURL",
"autoLoadDetectedSubs": "字幕を探知したら自動的にロードする",
"cleanScreenshot": "オーバーレイ非表示スクリーンショット",
"condensedPlaybackMinSkipInterval": "短縮プレイバックでスキップする時間の最小値",
"cropScreenshot": "スクリーンショットのクロッピング",
"displaySubtitles": "字幕表示オン/オフ",
"dragAndDrop": "字幕ファイルのドラッグ&ドロップを許可",
"subtitleListPreference": "字幕リストの表示設定",
"openSubtitleList": "字幕ロード時に字幕リストを開く",
"mining": "マイニング",
"miningKeyboardShortcuts": "マイニング関連のキーボードショートカット",
"misc": "その他",
"playback": "プレイバック",
"playbackKeyboardShortcuts": "再生関連のキーボードショートカット",
"recordAudio": "音声を記録する",
"screenshotCaptureDelay": "スクリーンショットの撮影タイミング",
"subtitles": "字幕",
"syncing": "同期",
"takeScreenshot": "スクリーンショットを撮る",
"updateAvailable": "アップデートがあります"
},
"videoDataSync": {
"emptySubtitleTrack": "空",
"loadSubtitlesFirst": "マイニングを開始する前に字幕をロードしてください。",
"rememberTrackPreference": "字幕トラックの選択を記憶する",
"selectSubtitles": "字幕を選択",
"subtitleTrack": "字幕トラック",
"videoName": "動画ファイル名"
},
"videoSelect": {
"multipleVideoElements": "複数の動画を探知しました",
"selectVideo": "asbplayer と同期する動画埋め込み要素を選択してください。",
"syncBeforeMine": "動画埋め込み要素のマイニングを開始する前に、動画と asbplayer を同期してください。選択した動画埋め込み要素を asbplayer と同期します。",
"videoElement": "動画埋め込み要素を選択"
},
"backgroundAudioRecordingPage": {
"description": "このページは asbplayer が音声を録音する際に使用します。"
}
},
"ftue": {
"welcome": "asbplayerへようこそ。",
"welcomeBody": "asbplayerの使い方は<0>readme</0>を参考にしてください。"
},
"info": {
"copiedSubtitle": "コピーしました:{{text}}",
"disabledAutoPause": "自動一時停止:オフ",
"disabledCondensedPlayback": "短縮プレイバック:オフ",
"disabledFastForwardPlayback": "早送りプレイバック:オフ",
"enabledAutoPause": "自動一時停止:オン",
"enabledCondensedPlayback": "短縮プレイバック:オン",
"enabledFastForwardPlayback": "早送りプレイバック:オン",
"exportedCard": "カードのエクスポート:{{result}}",
"playbackRate": "再生速度:{{rate}}",
"savedTimestamp": "保存しました:{{timestamp}}",
"updatedCard": "カードの更新:{{result}}",
"activeTabPermissionObtained": "音声記録が有効になりました。"
},
"landing": {
"cta": "字幕やメディアファイルをドラッグ&ドロップ、または<1>ファイルを選択</1>してください。",
"extensionNotInstalled": "Web上の動画と字幕を同期するために<1>Chrome 拡張機能</1>をインストールしてください。",
"extensionUpdateAvailable": "拡張機能の<1>アップデート</1>を公開しました。",
"noSubtitles": "字幕はありません",
"videoElementsDetected": "asbplayerを使用するには字幕をロードしてください。",
"noVideoElementsDetected": "動画を探知できませんでした。"
},
"activeTabPermissionRequest": {
"title": "音声記録を有効にしてください",
"grantedTitle": "音声記録が有効になりました",
"prompt": "音声記録を有効するにはブラウザの右上にあるasbplayerのアクションボタンをクリックしてください。",
"grantedPrompt": "音声記録が有効になりました。マイニングを始めてください。"
},
"settings": {
"addCustomCss": "カスタムCSSを追加",
"addCustomField": "カスタムフィールドを追加",
"anki": "Anki",
"ankiConnectUrl": "AnkiConnect の URL",
"audioField": "音声フィールド",
"audioPaddingEnd": "音声の余白終了",
"audioPaddingStart": "音声の余白開始",
"autoCopy": "現在の字幕を自動でクリップボードにコピーする",
"autoPauseAtSubtitleEnd": "字幕の終了時",
"autoPauseAtSubtitleStart": "字幕の開始時",
"autoPausePreference": "自動一時停止の設定",
"autoPausePreferenceHelperText": "自動一時停止を有効化する項目ではなく、自動一時停止がオンになっている時に一時停止するタイミングを設定する。",
"fastForwardModePlaybackRate": "早送りモードの再生速度",
"copyOnMine": "マイニングした字幕をクリップボードにコピー",
"corsHelperText": "<0>この動画</0>を参考に、{{origin}} が AnkiConnect 設定の webCorsOriginList に入っていることを確認してください。",
"customCssField": "CSS: {{styleKey}}",
"deck": "デッキ",
"definitionField": "詳細フィールド",
"extensionOverriddenBind": "拡張機能を優先",
"extensionShortcut": "拡張機能ショートカット",
"imageBasedSubtitleScaleFactor": "画像ベースの字幕の表示サイズ倍数",
"imageField": "画像フィールド",
"keyboardShortcuts": "キーボードショートカット",
"language": "言語",
"maxImageHeight": "画像の高さの最大値",
"maxImageWidth": "画像の幅の最大値",
"mining": "マイニング",
"miningHistoryStorageLimit": "マイニング履歴の保存数上限",
"clickToMineDefaultAction": "ボタンでマイニングした際のデフォルト動作",
"misc": "その他",
"mp3Preference": "音声を mp3 形式で再録音(低速)",
"noteType": "メモタイプ",
"preCacheSubtitleDom": "字幕DOMをキャッシュ",
"preCacheSubtitleDomHelperText": "この設定をオンにすると、asbplayerは隠れたDOM要素に字幕をレンダリングし、字幕が表示される際には既存の要素を再利用します。そのため、字幕のテキストは外部のコードによって永続的に変更可能となります。",
"recordingBind": "記録中",
"rememberSubtitleOffset": "字幕の表示タイミングを記憶する",
"sentenceField": "文フィールド",
"streamingVideo": "ストリーミングビデオ",
"styleKey": "スタイルのキー",
"styleValue": "スタイルの値",
"sourceField": "ソースフィールド",
"subtitleAppearance": "字幕の表示設定",
"subtitleBackgroundColor": "字幕の背景色",
"subtitleBackgroundOpacity": "字幕の背景の透明度",
"subtitleColor": "字幕の色",
"subtitleFontFamily": "字幕のフォントファミリー",
"subtitleOutlineColor": "字幕の縁取りの色",
"subtitleOutlineThickness": "字幕の縁取りの太さ",
"subtitleShadowColor": "字幕の影の色",
"subtitleShadowThickness": "字幕の影の太さ",
"subtitleOutlineThicknessHelperText": "字幕に縁取りが追加される。縁取りの線が重なっているように見える場合、別のフォントを試してみてください。",
"subtitlePositionOffset": "字幕表示位置の調整",
"subtitleAlignment": "字幕の表示位置",
"subtitleAlignmentBottom": "下部",
"subtitleAlignmentTop": "上部",
"subtitleRegexFilter": "字幕の正規表現フィルタ",
"subtitleRegexFilterTextReplacement": "字幕の正規表現フィルタの置き換えテキスト",
"subtitleSize": "字幕のサイズ",
"subtitleThickness": "字幕のフォントの太さ",
"surroundingSubtitlesCountRadius": "前後に表示される字幕の最大数",
"surroundingSubtitlesTimeRadius": "前後の字幕が表示される範囲(時間)",
"tags": "タグ",
"tagsHelperText": "テキストのリスト(カンマ「,」区切り)",
"theme": "テーマ",
"themeDark": "ダーク",
"themeLight": "ライト",
"title": "設定",
"unlockLocalFonts": "フォント検出の解除",
"unboundBind": "キーバインドなし",
"urlField": "URL フィールド",
"wordField": "単語フィールド"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "複数の字幕をマイニングするには、クリックし、押し続け、ドラッグしてください"
}
}

293
asbplayer-extension/asbplayer-locales/pl.json

@ -0,0 +1,293 @@
{
"action": {
"cancel": "Anuluj",
"copy": "Kopiuj",
"delete": "Usuń",
"downloadAudio": "Pobierz audio",
"downloadImage": "Pobierz obraz",
"downloadSubtitlesAsSrt": "Pobierz napisy w formacie SRT",
"jumpTo": "Przeskocz do ",
"ok": "OK",
"mineSubtitle": "Mine Subtitle",
"openFiles": "Otwórz pliki",
"loadSubtitles": "Load Subtitles",
"openApp": "Open App",
"openSidePanel": "Open Side Panel",
"mine": "Mine",
"updateLastCard": "Update Last Card",
"startRecording": "Start Recording",
"stopRecording": "Stop Recording",
"importSettings": "Import Settings",
"exportSettings": "Export Settings"
},
"postMineAction": {
"none": "None",
"showAnkiDialog": "Show Anki dialog",
"updateLastCard": "Update last card"
},
"ankiDialog": {
"applySelection": "Zastosuj wybór",
"audio": "Audio",
"audioFileLinkLost": "Link do pliku audio utracony przez przeładowanie strony",
"cannotUpdateAudio": "Klip audio nie może być zaktualizowany ponieważ był nagrany wcześniej",
"copyToClipboard": "Kopiuj do schowka ",
"definition": "Definicja",
"export": "Eksportuj",
"foundDuplicateNotes": "Znaleziono {{count}} notatek ze słowem \"{{word}}\" w polu \"{{field}}\"",
"foundNoDuplicateNote": "Nie znaleziono żadnych notatek ze słowem \"{{word}}\" w polu \"{{field}}\"",
"image": "Obraz ",
"imageFileLinkLost": "Link do pliku obrazu utracony przez przeładowanie strony",
"openInAnki": "Otwórz w Anki",
"rerecord": "Nagraj ponownie",
"resetSlider": "Resetuj",
"rewind": "Przewiń ",
"searchInAnki": "Szukaj w Anki",
"sentence": "Zdanie",
"source": "Źródło",
"tagList": "Lista ciągów znaków oddzielonych przecinkami",
"title": "Eksport Anki",
"updateLastCard": "Zaktualizuj ostatnią kartę",
"url": "URL",
"word": "Słowo ",
"zoomIn": "Przybliż ",
"zoomOut": "Oddal"
},
"bar": {
"donate": "Wesprzyj",
"help": "Pomoc",
"miningHistory": "Historia kopania",
"settings": "Ustawienia",
"submitIssue": "Zgłoś problem"
},
"binds": {
"adjustOffset": "Przestaw przesunięcie napisów o ±100ms",
"adjustOffsetToNextSubtitle": "Przestaw przesunięcie napisów tak",
"adjustOffsetToPreviousSubtitle": "Przestaw przesunięcie napisów tak",
"adjustOffsetToSubtitle": "Przestaw przesunięcie napisów tak",
"adjustPlaybackRate": "Przestaw prędkość odtwarzania o ±0.1",
"ankiExport": "Wykop bieżące napisy i otwórz okno dialogowe Anki",
"copySubtitle": "Wykop bieżące napisy",
"decreaseOffset": "Przestaw przesunięcie napisów o -100ms",
"decreasePlaybackRate": "Przestaw prędkość odtwarzania o -0.1",
"extensionAnkiDialog": "Wykop bieżące napisy i otwórz okno dialogowe eksportu Anki. Jeśli wideo jest zsynchronizowane bez pliku z napisami",
"extensionCopySubtitle": "Wykop bieżące napisy. Jeśli wideo jest zsynchronizowane bez pliku z napisami",
"extensionSelectSubtitleTrack": "Wybierz ścieżkę napisów do załadowania. ",
"extensionTakeScreenshot": "Manualnie wykonaj zrzut ekranu",
"extensionToggleRecording": "Manualne rozpocznij/zatrzymaj nagrywanie audio",
"extensionUpdateLastCard": "Zaktualizuj ostatnio utworzoną kartę Anki o media przechwycone przez asbplayer. Jeśli wideo jest zsynchronizowane bez pliku z napisami",
"increaseOffset": "Przestaw przesunięcie napisów o +100ms",
"increasePlaybackRate": "Przestaw prędkość odtwarzania o +0.1",
"resetOffset": "Wyzeruj przesunięcie napisów",
"seekBackward": "Przeskocz o 10 sekund do tył",
"seekBackwardOrForward": "Przeskocz o 10 sekund w tył/przód",
"seekForward": "Przeskocz o 10 sekund w przód",
"seekToBeginningOfCurrentSubtitle": "Przeskocz do początku bieżącego napisu",
"seekToNextSubtitle": "Przeskocz do następnego napisu ",
"seekToPreviousSubtitle": "Przeskocz do poprzedniego napisu",
"seekToSubtitle": "Przeskocz do poprzedniego/następnego napisu",
"takeScreenshot": "Manualnie wykonaj zrzut ekranu",
"toggleAsbplayerSubtitleTrack1": "Przełącz ścieżkę napisów 1 w asbplayer",
"toggleAsbplayerSubtitleTrack2": "Przełącz ścieżkę napisów 2 w asbplayer",
"toggleAsbplayerSubtitleTrack3": "Przełącz ścieżkę napisów 3 w asbplayer",
"toggleAsbplayerSubtitleTracks": "Przełącz ścieżki napisów w asbplayer",
"toggleAutoPause": "Przełącz automatyczną pauzę",
"toggleCondensedPlayback": "Przełącz odtwarzanie skondensowane",
"toggleFastForwardPlayback": "Toggle fast forward playback",
"togglePlay": "Odtwarzanie/pauza",
"toggleSubtitles": "Pokaż napisy",
"toggleVideoSubtitleTrack1": "Przełącz ścieżkę napisów 1 w wideo",
"toggleVideoSubtitleTrack2": "Przełącz ścieżkę napisów 2 w wideo",
"toggleVideoSubtitleTrack3": "Przełącz ścieżkę napisów 3 w wideo",
"toggleVideoSubtitleTracks": "Przełącz ścieżki napisów w wideo",
"updateLastCard": "Zaktualizuj ostatnio zapisaną kartę Anki o zrzuty ekranu",
"toggleSidePanel": "Toggle side panel"
},
"controls": {
"autoPauseMode": "Automatyczna pauza",
"condensedMode": "Skondensowana",
"fastForwardMode": "Fast-forward",
"normalMode": "Normalna",
"playbackRate": "Prędkość odtwarzania: {{rate}}",
"subtitleOffset": "Przesunięcie napisów",
"subtitleAlignment": "Subtitle Alignment",
"toggleSubtitles": "Toggle Subtitles",
"playbackMode": "Playback Mode",
"unloadVideo": "Unload Video",
"selectAudioTrack": "Select Audio Track",
"selectVideoElement": "Select Video Element",
"popOut": "Pop Out",
"popIn": "Pop In",
"toggleFullscreen": "Toggle Fullscreen",
"toggleTheaterMode": "Toggle Theater Mode",
"showSubtitlePlayer": "Show Subtitle List",
"hideSubtitlePlayer": "Hide Subtitle List"
},
"copyHistory": {
"blank": "Puste",
"downloadMinedSubsAsSrt": "Pobierz wykopane napisy jako plik SRT",
"exportToAnki": "Wyeksportuj do Anki",
"miningHistoryEmpty": "Historia kopania jest pusta. "
},
"error": {
"bothAudioAndVideNotAllowed": "Nie można załadować plików audio i wideo naraz",
"failedToLoadDirectory": "Nie udało się załadować katalogu",
"lostTabConnection": "Utracono połączenie z kartą {{tabName}}",
"onlyOneAudioFile": "Nie można otworzyć dwóch plików audio naraz",
"onlyOneDirectoryAllowed": "Nie można załadować więcej niż jeden katalog naraz",
"onlyOneVideoFile": "Nie można otworzyć dwóch plików wideo naraz",
"subdirectoriesNotAllowed": "Nie można załadowac katalogu z podkatalogami",
"subtitleFileNotOpen": "Plik napisów {{fileName}} nie jest otwarty.",
"unknownExtension": "Nie można rozpoznać rozszerzenia {{fileName}}",
"unsupportedExtension": "Niewspierane rozszerzenie {{extension}}",
"videoPlayerDragAndDropNotAllowed": "Odtwarzacz wideo nie może przyjąć upuszczonych plików. Zamiast tego upuść poza ramką wideo."
},
"extension": {
"settings": {
"asbplayerUrl": "URL asbplayer",
"autoLoadDetectedSubs": "Automatyczne ładowanie wykrytych napisów",
"cleanScreenshot": "Czyść zrzut ekranu",
"condensedPlaybackMinSkipInterval": "Minimalny interwał pominięcia odtwarzania skondensowanego",
"cropScreenshot": "Przycinaj zrzut ekranu",
"displaySubtitles": "Wyświetl napisy",
"dragAndDrop": "Pozwól na przeciąganie i upuszczanie plików z napisami",
"subtitleListPreference": "Subtitle list preference",
"openSubtitleList": "Open subtitle list when loading subtitles",
"mining": "Kopanie",
"miningKeyboardShortcuts": "Skróty klawiszowe kopania",
"misc": "Różne",
"playback": "Odtwarzanie",
"playbackKeyboardShortcuts": "Skróty klawiszowe odtwarzania",
"recordAudio": "Nagrywaj audio",
"screenshotCaptureDelay": "Opóźnienie przechwycenia zrzutu ekranu",
"subtitles": "Napisy",
"syncing": "Synchronizacja",
"takeScreenshot": "Rób zrzut ekranu",
"updateAvailable": "Dostępna aktualizacja"
},
"videoDataSync": {
"emptySubtitleTrack": "Empty",
"loadSubtitlesFirst": "Napisy muszą być załadowane zanim zaczniesz kopać.",
"rememberTrackPreference": "Remember these track choices for this site",
"selectSubtitles": "Wybierz napisy",
"subtitleTrack": "Ścieżka napisów",
"videoName": "Nazwa wideo"
},
"videoSelect": {
"multipleVideoElements": "Wykryto wiele elementów wideo",
"selectVideo": "Wybierz element wideo do synchronizacji z asbplayer.",
"syncBeforeMine": "Element wideo musi być najpierw zsynchronizowany z asbplayer aby mógł być wykopany. Wybierz element wideo do synchronizacji z asbplayer.",
"videoElement": "Element wideo"
},
"backgroundAudioRecordingPage": {
"description": "Ta strona jest używana przez asbplayer do przechwytywania audio."
}
},
"ftue": {
"welcome": "Welcome to asbplayer.",
"welcomeBody": "Check out the <0>readme</0> to see how to get started."
},
"info": {
"copiedSubtitle": "Skopiowano: {{text}}",
"disabledAutoPause": "Automatyczna pauza: Wyłączona",
"disabledCondensedPlayback": "Skondensowane odtwarzanie: Wyłączone",
"disabledFastForwardPlayback": "Fast forward playback: Off",
"enabledAutoPause": "Automatyczna pauza: Włączona",
"enabledCondensedPlayback": "Odtwarzanie skondensowane: Włączone",
"enabledFastForwardPlayback": "Fast forward playback: On",
"exportedCard": "Wyeksportowana karta: {{result}}",
"playbackRate": "Playback Rate: {{rate}}",
"savedTimestamp": "Zapisano: {{timestamp}}",
"updatedCard": "Zaktualizowana karta: {{result}}",
"activeTabPermissionObtained": "Audio recording is now enabled for this tab."
},
"landing": {
"cta": "Przenieś i upuść napisy i pliki medialne, lub <1>przeglądaj</1>.",
"extensionNotInstalled": "Zainstaluj <1>rozszerzenie Chrome</1> aby zsynchronizować napisy ze strumieniowanym wideo",
"extensionUpdateAvailable": "Dostępna jest <1>aktualizacja</1> rozszerzenia.",
"noSubtitles": "No subtitles",
"videoElementsDetected": "Load subtitles onto a video to start using asbplayer.",
"noVideoElementsDetected": "No videos detected."
},
"activeTabPermissionRequest": {
"title": "Enable audio recording",
"grantedTitle": "Audio recording enabled",
"prompt": "Click on the asbplayer action button in the top-right of the browser window to enable audio recording for this tab.",
"grantedPrompt": "Audio recording has been enabled for this tab. You can now begin mining."
},
"settings": {
"addCustomCss": "Add Custom CSS",
"addCustomField": "Dodaj niestandardowe pole",
"anki": "Anki",
"ankiConnectUrl": "URL Anki Connect",
"audioField": "Pole na audio",
"audioPaddingEnd": "Padding audio z końca",
"audioPaddingStart": "Padding audio z początku ",
"autoCopy": "Automatycznie kopiuj bieżące napisy to schowka ",
"autoPauseAtSubtitleEnd": "Na końcu napisu",
"autoPauseAtSubtitleStart": "Na początku napisu ",
"autoPausePreference": "Preferencja automatycznej pauzy",
"autoPausePreferenceHelperText": "Nie włącza automatycznej pauzy. Ustawia preferencję kiedy się zatrzymać gdy automatyczna pauza jest włączona. ",
"fastForwardModePlaybackRate": "Fast-forward Mode Playback Rate",
"copyOnMine": "Skopiuj wykopane napisy do schowka",
"corsHelperText": "Upewnij się że {{origin}} jest w liście webCorsOriginList w twoich ustawieniach AnkiConnect tak",
"customCssField": "CSS: {{styleKey}}",
"deck": "Talia",
"definitionField": "Pole na definicję ",
"extensionOverriddenBind": "Nadpisane",
"extensionShortcut": "Skrót z rozszerzenia",
"imageBasedSubtitleScaleFactor": "Skalowanie napisów na bazie obrazu",
"imageField": "Pole na obraz ",
"keyboardShortcuts": "Skróty klawiszowe",
"language": "Język",
"maxImageHeight": "Maksymalna wysokość obrazu",
"maxImageWidth": "Maksymalna szerokość obrazu ",
"mining": "Kopanie",
"miningHistoryStorageLimit": "Limit przechowywania historii kopania",
"clickToMineDefaultAction": "Mining button default action",
"misc": "Różne",
"mp3Preference": "Ponowne kodowanie dźwięku do formatu mp3 (wolniejsze)",
"noteType": "Typ notatek",
"preCacheSubtitleDom": "Pre-cache Subtitle DOM",
"preCacheSubtitleDomHelperText": "If enabled, asbplayer will pre-render subtitle text elements in an offscreen document, and re-use those elements for subtitle display. This allows external code to persistently modify subtitle text before it is displayed.",
"recordingBind": "Nagrywanie",
"rememberSubtitleOffset": "Zapamiętaj przesunięcie napisów",
"sentenceField": "Pole na zdanie",
"streamingVideo": "Streaming Video",
"styleKey": "Style Key",
"styleValue": "Style Value",
"sourceField": "Pole na źródło",
"subtitleAppearance": "Wygląd napisów",
"subtitleBackgroundColor": "Kolor tła napisów",
"subtitleBackgroundOpacity": "Krycie tła napisów",
"subtitleColor": "Kolor napisów",
"subtitleFontFamily": "Rodzina czcionek napisów",
"subtitleOutlineColor": "Kolor konturu napisów",
"subtitleOutlineThickness": "Grubość konturu napisów",
"subtitleShadowColor": "Subtitle Shadow Color",
"subtitleShadowThickness": "Subtitle Shadow Thickness",
"subtitleOutlineThicknessHelperText": "Adds an outline around subtitle text. If this causes overlapping lines, try using a different font.",
"subtitlePositionOffset": "Przesunięcie pozycji napisów",
"subtitleAlignment": "Wyrównanie napisów",
"subtitleAlignmentBottom": "Dół",
"subtitleAlignmentTop": "Góra",
"subtitleRegexFilter": "Filtr Regex napisów",
"subtitleRegexFilterTextReplacement": "Zamiana tekstu z filtru Regex napisów",
"subtitleSize": "Wielkość napisów",
"subtitleThickness": "Subtitle Font Thickness",
"surroundingSubtitlesCountRadius": "Limit liczby napisów otaczających",
"surroundingSubtitlesTimeRadius": "Limit czasu napisów otaczających",
"tags": "Tagi",
"tagsHelperText": "Lista ciągów znaków oddzielonych przecinkami",
"theme": "Motyw",
"themeDark": "Ciemny ",
"themeLight": "Jasny",
"title": "Ustawienia",
"unlockLocalFonts": "Click to unlock font menu",
"unboundBind": "Nieprzypisane",
"urlField": "Pole na URL",
"wordField": "Pole na słowo "
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Click, hold, and drag to mine multiple subtitles"
}
}

293
asbplayer-extension/asbplayer-locales/pt_BR.json

@ -0,0 +1,293 @@
{
"action": {
"cancel": "Cancelar",
"copy": "Copiar",
"delete": "Excluir",
"downloadAudio": "Baixar áudio",
"downloadImage": "Baixar imagem",
"downloadSubtitlesAsSrt": "Baixar legenda como SRT",
"jumpTo": "Pular para",
"ok": "OK",
"mineSubtitle": "Minerar legenda",
"openFiles": "Abrir arquivos",
"loadSubtitles": "Carregar legenda",
"openApp": "Abrir aplicativo",
"openSidePanel": "Abrir painel lateral",
"mine": "Minerar",
"updateLastCard": "Atualizar último card",
"startRecording": "Iniciar gravação",
"stopRecording": "Parar gravação",
"importSettings": "Importar configurações",
"exportSettings": "Exportar configurações"
},
"postMineAction": {
"none": "Nada",
"showAnkiDialog": "Mostrar caixa de diálogo do Anki",
"updateLastCard": "Atualizar último card"
},
"ankiDialog": {
"applySelection": "Aplicar seleção",
"audio": "Áudio",
"audioFileLinkLost": "Link de arquivo de áudio perdido devido ao recarregamento da página",
"cannotUpdateAudio": "Clipe de áudio não pôde ser atualizado porque é pre-gravado",
"copyToClipboard": "Copiar para a área de transferência",
"definition": "Definição",
"export": "Exportar",
"foundDuplicateNotes": "Encontrado {{count}} nota(s) com a palavra \"{{word}}\" no campo \"{{field}}\"",
"foundNoDuplicateNote": "Nenhuma nota encontrada com a palavra \"{{word}}\" no campo \"{{field}}\"",
"image": "Imagem",
"imageFileLinkLost": "Link de arquivo de imagem perdido devido ao recarregamento da página",
"openInAnki": "Abrir no Anki",
"rerecord": "Regravar",
"resetSlider": "Resetar",
"rewind": "Retroceder",
"searchInAnki": "Pesquisar no Anki",
"sentence": "Sentença",
"source": "Fonte",
"tagList": "Lista de strings separadas por vírgulas",
"title": "Exportar para o Anki",
"updateLastCard": "Atualizar último card",
"url": "URL",
"word": "Palavra",
"zoomIn": "Ampliar",
"zoomOut": "Reduzir"
},
"bar": {
"donate": "Doar",
"help": "Ajuda",
"miningHistory": "Histórico de mineração",
"settings": "Configurações",
"submitIssue": "Reportar problemas"
},
"binds": {
"adjustOffset": "Ajuste o atraso da legenda em ±100 ms",
"adjustOffsetToNextSubtitle": "Ajusta o atraso da legenda para que a próxima legenda esteja no timestamp atual",
"adjustOffsetToPreviousSubtitle": "Ajusta o atraso da legenda para que a legenda anterior esteja no timestamp atual",
"adjustOffsetToSubtitle": "Ajuste o atraso da legenda para que a legenda anterior/próxima esteja no timestamp atual",
"adjustPlaybackRate": "Ajuste a taxa de reprodução em ±0.1",
"ankiExport": "Minera a legenda atual e abre a caixa de diálogo do Anki",
"copySubtitle": "Minera a legenda atual",
"decreaseOffset": "Ajusta o atraso da legenda em -100ms",
"decreasePlaybackRate": "Ajusta a taxa de reprodução em -0.1",
"extensionAnkiDialog": "Minera a legenda atual e abre a caixa de diálogo 'Exportar para o Anki'. Quando o vídeo está sincronizado sem um arquivo de legenda, inicia/para a gravação de áudio.",
"extensionCopySubtitle": "Minera a legenda atual. Quando o vídeo está sincronizado sem um arquivo de legenda, inicia/para a gravação de áudio.",
"extensionSelectSubtitleTrack": "Seleciona faixas de legendas para carregar.",
"extensionTakeScreenshot": "Tira uma captura de tela manualmente, substituindo a que é tirada automaticamente ao minerar.",
"extensionToggleRecording": "Inicia/para a gravação de áudio manualmente, mesmo quando um arquivo de legenda está carregado.",
"extensionUpdateLastCard": "Atualiza o último card do Anki criado com a mídia capturada pelo asbplayer. Quando o vídeo é sincronizado sem um arquivo de legenda, inicia/para a gravação de áudio.",
"increaseOffset": "Ajusta atraso da legenda em +100ms",
"increasePlaybackRate": "Ajusta taxa de reprodução em +0.1",
"resetOffset": "Reseta o atraso da legenda",
"seekBackward": "Retrocede 10 segundos",
"seekBackwardOrForward": "Retroceda/avança 10 segundos",
"seekForward": "Avança 10 segundos",
"seekToBeginningOfCurrentSubtitle": "Vai para o início da legenda atual",
"seekToNextSubtitle": "Vai para a próxima legenda",
"seekToPreviousSubtitle": "Vai para a legenda anterior",
"seekToSubtitle": "Vá para a legenda anterior/próxima",
"takeScreenshot": "Tira uma captura de tela manualmente, substituindo a que é tirada automaticamente ao minerar",
"toggleAsbplayerSubtitleTrack1": "Alternar a faixa de legenda 1 no asbplayer",
"toggleAsbplayerSubtitleTrack2": "Alternar a faixa de legenda 2 no asbplayer",
"toggleAsbplayerSubtitleTrack3": "Alternar a faixa de legenda 3 no asbplayer",
"toggleAsbplayerSubtitleTracks": "Alterne a faixa de legenda no asbplayer",
"toggleAutoPause": "Alternar pausa automática",
"toggleCondensedPlayback": "Alternar reprodução condensada",
"toggleFastForwardPlayback": "Alternar reprodução de avanço rápido",
"togglePlay": "Play/pause",
"toggleSubtitles": "Alternar legendas",
"toggleVideoSubtitleTrack1": "Alternar faixa de legenda 1 no vídeo",
"toggleVideoSubtitleTrack2": "Alternar faixa de legenda 2 no vídeo",
"toggleVideoSubtitleTrack3": "Alternar faixa de legenda 3 no vídeo",
"toggleVideoSubtitleTracks": "Alterne a faixa de legenda no vídeo",
"updateLastCard": "Atualiza o último cartão criado no Anki com captura de tela, áudio, etc. do asbplayer.",
"toggleSidePanel": "Alternar painel lateral"
},
"controls": {
"autoPauseMode": "Pausa automática",
"condensedMode": "Condensado",
"fastForwardMode": "Avanço rápido",
"normalMode": "Normal",
"playbackRate": "Taxa de reprodução",
"subtitleOffset": "Atraso da legenda",
"subtitleAlignment": "Alinhamento da legenda",
"toggleSubtitles": "Ativar/Desativar legendas",
"playbackMode": "Modo de reprodução",
"unloadVideo": "Descarregar vídeo",
"selectAudioTrack": "Selecionar faixa de áudio",
"selectVideoElement": "Selecionar elemento de vídeo",
"popOut": "Destacar",
"popIn": "Recuar",
"toggleFullscreen": "Alternar tela cheia",
"toggleTheaterMode": "Alternar modo teatro",
"showSubtitlePlayer": "Mostrar lista de legendas",
"hideSubtitlePlayer": "Ocultar lista de legendas"
},
"copyHistory": {
"blank": "Em branco",
"downloadMinedSubsAsSrt": "Baixar legendas mineradas como SRT",
"exportToAnki": "Exportar para o Anki",
"miningHistoryEmpty": "O histórico de mineração está vazio."
},
"error": {
"bothAudioAndVideNotAllowed": "Não é possível carregar simultaneamente um arquivo de áudio e um arquivo de vídeo",
"failedToLoadDirectory": "Falha ao carregar diretório",
"lostTabConnection": "Perda de conexão com a guia: {{tabName}}",
"onlyOneAudioFile": "Não é possível abrir dois arquivos de áudio simultaneamente",
"onlyOneDirectoryAllowed": "Não é possível carregar mais de um diretório por vez",
"onlyOneVideoFile": "Não é possível abrir dois arquivos de vídeo simultaneamente",
"subdirectoriesNotAllowed": "Não é possível carregar um diretório com subdiretórios",
"subtitleFileNotOpen": "Arquivo de legenda {{fileName}} não está aberto.",
"unknownExtension": "Não é possível determinar a extensão de {{fileName}}",
"unsupportedExtension": "Extensão não suportada: {{extension}}",
"videoPlayerDragAndDropNotAllowed": "O player de vídeo não pode receber arquivos arrastados. Solte-os fora do quadro do vídeo."
},
"extension": {
"settings": {
"asbplayerUrl": "URL do aplicativo",
"autoLoadDetectedSubs": "Carregar automaticamente legendas detectadas",
"cleanScreenshot": "Capturar tela limpa",
"condensedPlaybackMinSkipInterval": "Intervalo mínimo de salto para reprodução condensada",
"cropScreenshot": "Recortar captura de tela",
"displaySubtitles": "Exibir legendas",
"dragAndDrop": "Permitir ação de arrastar e soltar para arquivos de legenda",
"subtitleListPreference": "Preferência da lista de legendas",
"openSubtitleList": "Abrir lista de legendas ao carregar legendas",
"mining": "Mineração",
"miningKeyboardShortcuts": "Atalhos de Teclado para Mineração",
"misc": "Diversos",
"playback": "Reprodução",
"playbackKeyboardShortcuts": "Atalhos de Teclado para Reprodução",
"recordAudio": "Gravar áudio",
"screenshotCaptureDelay": "Atraso de captura de tela",
"subtitles": "Legenda",
"syncing": "Sincronização",
"takeScreenshot": "Tirar captura de tela",
"updateAvailable": "Atualização disponível"
},
"videoDataSync": {
"emptySubtitleTrack": "Vazio",
"loadSubtitlesFirst": "Legendas devem ser carregadas antes que você possa começar a minerar.",
"rememberTrackPreference": "Lembrar dessas escolhas de faixa para este site",
"selectSubtitles": "Selecionar legenda",
"subtitleTrack": "Selecionar faixa",
"videoName": "Nome do vídeo"
},
"videoSelect": {
"multipleVideoElements": "Detectados Múltiplos Elementos de Vídeo",
"selectVideo": "Selecione um elemento de vídeo para sincronizá-lo com o asbplayer.",
"syncBeforeMine": "Um elemento de vídeo deve ser sincronizado com o asbplayer antes que ele possa ser minerado. Selecione um elemento de vídeo para sincronizá-lo com o asbplayer.",
"videoElement": "Elemento de vídeo"
},
"backgroundAudioRecordingPage": {
"description": "Esta página é usada pelo asbplayer para capturar áudio."
}
},
"ftue": {
"welcome": "Welcome to asbplayer.",
"welcomeBody": "Check out the <0>readme</0> to see how to get started."
},
"info": {
"copiedSubtitle": "Copiado: {{text}}",
"disabledAutoPause": "Pausa automática: Off",
"disabledCondensedPlayback": "Reprodução condensada: Off",
"disabledFastForwardPlayback": "Reprodução de avanço rápido: Off",
"enabledAutoPause": "Pausa automática: On",
"enabledCondensedPlayback": "Reprodução condensada: On",
"enabledFastForwardPlayback": "Reprodução de avanço rápido: On",
"exportedCard": "Card exportado: {{result}}",
"playbackRate": "Taxa de reprodução: {{rate}}",
"savedTimestamp": "Salvo: {{timestamp}}",
"updatedCard": "Atualizar card: {{result}}",
"activeTabPermissionObtained": "A gravação de áudio agora está habilitada para essa guia."
},
"landing": {
"cta": "Arraste e solte arquivos de mídia e legenda, ou <1>procure</1>.",
"extensionNotInstalled": "Instale a <1>Extensão para o chrome</1> para sincronizar as legendas com o streaming de vídeo.",
"extensionUpdateAvailable": "Uma <1>atualização</1> para a extensão está disponível.",
"noSubtitles": "Sem legendas",
"videoElementsDetected": "Carregar legendas em um vídeo para começar a usar o asbplayer.",
"noVideoElementsDetected": "Nenhum vídeo detectado."
},
"activeTabPermissionRequest": {
"title": "Habilitar gravação de áudio.",
"grantedTitle": "Gravação de áudio habilitada.",
"prompt": "Clique no botão de ação do asbplayer no canto superior direito da janela do navegador para habilitar a gravação de áudio para esta guia.",
"grantedPrompt": "A gravação de áudio foi habilitada para esta guia. Agora você pode começar a minerar."
},
"settings": {
"addCustomCss": "Adicionar CSS customizado",
"addCustomField": "Adicionar campo customizado",
"anki": "Anki",
"ankiConnectUrl": "URL do Anki Connect",
"audioField": "Campo de áudio",
"audioPaddingEnd": "Fim do preenchimento de áudio",
"audioPaddingStart": "Início do preenchimento de áudio",
"autoCopy": "Copiar automaticamente a legenda atual para a área de transferência",
"autoPauseAtSubtitleEnd": "No final da legenda",
"autoPauseAtSubtitleStart": "No início da legenda",
"autoPausePreference": "Preferência de pausa automática",
"autoPausePreferenceHelperText": "Não habilita a pausa automática. Define a preferência de quando pausar quando a pausa automática estiver habilitada.",
"fastForwardModePlaybackRate": "Taxa de reprodução no modo de avanço rápido",
"copyOnMine": "Copiar legenda minerada para a área de transferência",
"corsHelperText": "Certifique-se de que {{origin}} esteja na webCorsOriginList em suas configurações do AnkiConnect, como neste <0>vídeo</0>.",
"customCssField": "CSS: {{styleKey}}",
"deck": "Baralho",
"definitionField": "Campo de definição",
"extensionOverriddenBind": "Sobreposto",
"extensionShortcut": "Atalho da extensão",
"imageBasedSubtitleScaleFactor": "Fator de escala para legendas baseadas em Imagem",
"imageField": "Campo de imagem",
"keyboardShortcuts": "Atalhos de teclado",
"language": "Idioma",
"maxImageHeight": "Altura máxima da imagem",
"maxImageWidth": "Largura máxima da Imagem",
"mining": "Mineração",
"miningHistoryStorageLimit": "Limite de armazenamento do histórico de mineração",
"clickToMineDefaultAction": "Ação padrão do botão de mineração",
"misc": "Diversos",
"mp3Preference": "Recodificar áudio como MP3 (mais lento)",
"noteType": "Tipo de nota",
"preCacheSubtitleDom": "Pré-carregar DOM de Legenda",
"preCacheSubtitleDomHelperText": "Ao ser habilitado, o asbplayer antecipa a renderização de elementos de texto de legendas em uma área fora da tela, reutilizando esses elementos para a exibição de legendas. Essa abordagem possibilita a modificação persistente do texto da legenda por meio de código externo antes de sua apresentação.",
"recordingBind": "Gravando",
"rememberSubtitleOffset": "Lembrar do atraso da legenda",
"sentenceField": "Campo da sentença",
"streamingVideo": "Streaming de vídeo",
"styleKey": "Tecla de estilo",
"styleValue": "Valor de estilo",
"sourceField": "Campo da fonte",
"subtitleAppearance": "Aparência da legenda",
"subtitleBackgroundColor": "Cor de fundo da legenda",
"subtitleBackgroundOpacity": "Opacidade do fundo da legenda",
"subtitleColor": "Cor da legenda",
"subtitleFontFamily": "Família de fonte da legenda",
"subtitleOutlineColor": "Cor do contorno da legenda",
"subtitleOutlineThickness": "Expessura do contorno da legenda",
"subtitleShadowColor": "Cor da sombra da legenda",
"subtitleShadowThickness": "Expessura da sombra da legenda",
"subtitleOutlineThicknessHelperText": "Adiciona um contorno ao redor do texto da legenda. Se isso causar sobreposição de linhas, tente usar uma fonte diferente.",
"subtitlePositionOffset": "Deslocamento da posição da legenda a partir da parte inferior",
"subtitleAlignment": "Alinhamento da legenda",
"subtitleAlignmentBottom": "Inferior",
"subtitleAlignmentTop": "Superior",
"subtitleRegexFilter": "Filtro regex da legenda",
"subtitleRegexFilterTextReplacement": "Substituição de texto do filtro regex da legenda",
"subtitleSize": "Tamanho da legenda",
"subtitleThickness": "Expessura da fonte da legenda",
"surroundingSubtitlesCountRadius": "Raio de contagem de legendas ao redor",
"surroundingSubtitlesTimeRadius": "Raio de tempo das legendas ao redor",
"tags": "Tags",
"tagsHelperText": "Lista de strings separadas por vírgulas",
"theme": "Tema",
"themeDark": "Escuro",
"themeLight": "Claro",
"title": "Configurações",
"unlockLocalFonts": "Clique para desbloquear o menu de fontes",
"unboundBind": "Não vinculado",
"urlField": "Campo da URL",
"wordField": "Campo da palavra"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Clique, segure e arraste para minerar múltiplas legendas"
}
}

293
asbplayer-extension/asbplayer-locales/zh_CN.json

@ -0,0 +1,293 @@
{
"action": {
"cancel": "取消",
"copy": "复制",
"delete": "删除",
"downloadAudio": "下载音频",
"downloadImage": "下载图像",
"downloadSubtitlesAsSrt": "下载字幕保存为srt文件",
"jumpTo": "跳转到",
"ok": "确认",
"mineSubtitle": "Mine Subtitle",
"openFiles": "打开文件",
"loadSubtitles": "Load Subtitles",
"openApp": "Open App",
"openSidePanel": "Open Side Panel",
"mine": "Mine",
"updateLastCard": "Update Last Card",
"startRecording": "Start Recording",
"stopRecording": "Stop Recording",
"importSettings": "Import Settings",
"exportSettings": "Export Settings"
},
"postMineAction": {
"none": "None",
"showAnkiDialog": "Show Anki dialog",
"updateLastCard": "Update last card"
},
"ankiDialog": {
"applySelection": "应用选中时间范围",
"audio": "音频",
"audioFileLinkLost": "由于页面刷新,音频文件链接丢失",
"cannotUpdateAudio": "音频剪辑无法更新,因为它已经被录制过",
"copyToClipboard": "复制到剪贴板",
"definition": "释义",
"export": "导出到Anki",
"foundDuplicateNotes": "已发现{{count}}张 {{field}} 字段中含有单词 {{word}} 的卡片",
"foundNoDuplicateNote": "未发现 {{field}} 字段中含有单词 {{word}} 的卡片",
"image": "图像",
"imageFileLinkLost": "由于页面重新加载,图像文件链接丢失",
"openInAnki": "在Anki中打开",
"rerecord": "重新录制音频",
"resetSlider": "重置",
"rewind": "倒带",
"searchInAnki": "在Anki中搜索",
"sentence": "语句",
"source": "来源",
"tagList": "逗号分隔的字符串列表",
"title": "Anki导出",
"updateLastCard": "更新最后一张插入Anki的卡牌",
"url": "URL",
"word": "单词",
"zoomIn": "缩小",
"zoomOut": "放大"
},
"bar": {
"donate": "捐赠作者",
"help": "帮助",
"miningHistory": "词汇挖矿历史",
"settings": "设置",
"submitIssue": "提交问题(github)"
},
"binds": {
"adjustOffset": "调整字幕偏移量(±100ms)",
"adjustOffsetToNextSubtitle": "调整字幕偏移量,使下一个字幕位于当前时间戳",
"adjustOffsetToPreviousSubtitle": "调整字幕偏移量,使上一个字幕处于当前时间戳",
"adjustOffsetToSubtitle": "调整字幕偏移量,使上一个/下一个字幕处于当前时间戳",
"adjustPlaybackRate": "调整播放速率(±0.1)",
"ankiExport": "挖掘当前字幕并打开Anki对话框",
"copySubtitle": "挖掘当前字幕",
"decreaseOffset": "字幕偏移量-100ms",
"decreasePlaybackRate": "降低播放速率(-0.1)",
"extensionAnkiDialog": "挖掘当前字幕并打开Anki导出对话框。当视频在没有字幕文件的情况下同步时,开始/停止录制音频。",
"extensionCopySubtitle": "挖掘当前字幕。当视频在没有字幕文件的情况下同步时,开始/停止录制音频。",
"extensionSelectSubtitleTrack": "选择要加载的字幕音轨。",
"extensionTakeScreenshot": "手动拍摄屏幕截图,覆盖挖掘时自动拍摄的屏幕截图。",
"extensionToggleRecording": "手动启动/停止音频录制,即使加载了字幕文件。",
"extensionUpdateLastCard": "使用asbplayer捕获的媒体更新上次创建的Anki卡。当视频在没有字幕文件的情况下同步时,开始/停止录制音频。",
"increaseOffset": "字幕偏移量+100ms",
"increasePlaybackRate": "增加播放速率(+0.1)",
"resetOffset": "重置字幕偏移量为0",
"seekBackward": "向后搜索10秒",
"seekBackwardOrForward": "向后/向前搜索10秒",
"seekForward": "向前搜索10秒",
"seekToBeginningOfCurrentSubtitle": "搜索到当前字幕的开头",
"seekToNextSubtitle": "查找下一个字幕",
"seekToPreviousSubtitle": "查找上一个/下一个字幕",
"seekToSubtitle": "查找上一个/下一个字幕",
"takeScreenshot": "手动拍摄屏幕截图,覆盖挖掘时自动拍摄的屏幕截图",
"toggleAsbplayerSubtitleTrack1": "切换asbplayer中的字幕音轨1",
"toggleAsbplayerSubtitleTrack2": "切换asbplayer中的字幕音轨2",
"toggleAsbplayerSubtitleTrack3": "切换asbplayer中的字幕音轨3",
"toggleAsbplayerSubtitleTracks": "在asbplayer中切换字幕音轨",
"toggleAutoPause": "切换自动暂停",
"toggleCondensedPlayback": "切换压缩播放",
"toggleFastForwardPlayback": "Toggle fast forward playback",
"togglePlay": "播放/暂停",
"toggleSubtitles": "切换字幕",
"toggleVideoSubtitleTrack1": "切换视频中的字幕音轨1",
"toggleVideoSubtitleTrack2": "切换视频中的字幕音轨2",
"toggleVideoSubtitleTrack3": "切换视频中的字幕音轨3",
"toggleVideoSubtitleTracks": "切换视频中的字幕音轨",
"updateLastCard": "使用asbplayer捕获的屏幕截图、音频等更新上次创建的Anki卡。",
"toggleSidePanel": "Toggle side panel"
},
"controls": {
"autoPauseMode": "自动暂停",
"condensedMode": "冷凝",
"fastForwardMode": "Fast-forward",
"normalMode": "典型的",
"playbackRate": "播放速率",
"subtitleOffset": "字幕偏移",
"subtitleAlignment": "Subtitle Alignment",
"toggleSubtitles": "Toggle Subtitles",
"playbackMode": "Playback Mode",
"unloadVideo": "Unload Video",
"selectAudioTrack": "Select Audio Track",
"selectVideoElement": "Select Video Element",
"popOut": "Pop Out",
"popIn": "Pop In",
"toggleFullscreen": "Toggle Fullscreen",
"toggleTheaterMode": "Toggle Theater Mode",
"showSubtitlePlayer": "Show Subtitle List",
"hideSubtitlePlayer": "Hide Subtitle List"
},
"copyHistory": {
"blank": "空白的",
"downloadMinedSubsAsSrt": "下载已挖掘字幕作为SRT文件",
"exportToAnki": "导出到Anki",
"miningHistoryEmpty": "挖掘历史记录为空。"
},
"error": {
"bothAudioAndVideNotAllowed": "无法同时加载音频和视频文件",
"failedToLoadDirectory": "未能加载目录",
"lostTabConnection": "与选项卡的连接丢失:{{tabName}}",
"onlyOneAudioFile": "无法同时打开两个音频文件",
"onlyOneDirectoryAllowed": "一次不能加载多个目录",
"onlyOneVideoFile": "无法同时打开两个视频文件",
"subdirectoriesNotAllowed": "无法加载包含子目录的目录",
"subtitleFileNotOpen": "字幕文件{{fileName}}未打开。",
"unknownExtension": "无法确定{{fileName}}的扩展名类型",
"unsupportedExtension": "不支持的文件类型{{extension}}",
"videoPlayerDragAndDropNotAllowed": "视频播放器无法接收拖放的文件。将其放到视频帧之外。"
},
"extension": {
"settings": {
"asbplayerUrl": "asbplayerURL",
"autoLoadDetectedSubs": "自动加载检测到的字幕",
"cleanScreenshot": "干净的屏幕截图",
"condensedPlaybackMinSkipInterval": "压缩播放最小跳过间隔",
"cropScreenshot": "裁剪屏幕截图",
"displaySubtitles": "显示字幕",
"dragAndDrop": "允许拖放字幕文件",
"subtitleListPreference": "Subtitle list preference",
"openSubtitleList": "Open subtitle list when loading subtitles",
"mining": "采矿",
"miningKeyboardShortcuts": "挖掘键盘快捷键",
"misc": "杂项",
"playback": "播放",
"playbackKeyboardShortcuts": "播放键盘快捷键",
"recordAudio": "录制音频",
"screenshotCaptureDelay": "屏幕截图捕获延迟",
"subtitles": "字幕",
"syncing": "正在同步",
"takeScreenshot": "截屏",
"updateAvailable": "可用更新"
},
"videoDataSync": {
"emptySubtitleTrack": "空的",
"loadSubtitlesFirst": "必须先加载字幕,然后才能开始挖掘。",
"rememberTrackPreference": "Remember these track choices for this site",
"selectSubtitles": "选择字幕",
"subtitleTrack": "字幕轨道",
"videoName": "视频名称"
},
"videoSelect": {
"multipleVideoElements": "检测到多个视频元素",
"selectVideo": "选择一个视频元素以将其与asbplayer同步。",
"syncBeforeMine": "视频元素必须与asbplayer同步,然后才能进行挖掘。选择一个视频元素以将其与asbplayer同步。",
"videoElement": "视频元素"
},
"backgroundAudioRecordingPage": {
"description": "此页面由asbplayer用于捕获音频。"
}
},
"ftue": {
"welcome": "Welcome to asbplayer.",
"welcomeBody": "Check out the <0>readme</0> to see how to get started."
},
"info": {
"copiedSubtitle": "已复制:{{text}}",
"disabledAutoPause": "自动暂停:关闭",
"disabledCondensedPlayback": "浓缩播放:关闭",
"disabledFastForwardPlayback": "Fast forward playback: Off",
"enabledAutoPause": "自动暂停:打开",
"enabledCondensedPlayback": "浓缩播放:打开",
"enabledFastForwardPlayback": "Fast forward playback: On",
"exportedCard": "导出的卡:{{result}}",
"playbackRate": "播放速率:{{Rate}}",
"savedTimestamp": "已保存:{{时间戳}}",
"updatedCard": "更新的卡:{{result}}",
"activeTabPermissionObtained": "Audio recording is now enabled for this tab."
},
"landing": {
"cta": "拖放字幕和媒体文件,或<1>浏览</1>。",
"extensionNotInstalled": "安装<1>Chrome扩展</1>以将字幕与流媒体视频同步",
"extensionUpdateAvailable": "扩展<1>更新</1>可用。",
"noSubtitles": "没有字幕",
"videoElementsDetected": "Load subtitles onto a video to start using asbplayer.",
"noVideoElementsDetected": "No videos detected."
},
"activeTabPermissionRequest": {
"title": "Enable audio recording",
"grantedTitle": "Audio recording enabled",
"prompt": "Click on the asbplayer action button in the top-right of the browser window to enable audio recording for this tab.",
"grantedPrompt": "Audio recording has been enabled for this tab. You can now begin mining."
},
"settings": {
"addCustomCss": "添加自定义CSS",
"addCustomField": "添加自定义字段",
"anki": "Anki",
"ankiConnectUrl": "Anki连接URL",
"audioField": "音频字段",
"audioPaddingEnd": "音频填充结束",
"audioPaddingStart": "音频填充开始",
"autoCopy": "自动将当前字幕复制到剪贴板",
"autoPauseAtSubtitleEnd": "在字幕末尾",
"autoPauseAtSubtitleStart": "在字幕开头",
"autoPausePreference": "自动暂停首选项",
"autoPausePreferenceHelperText": "不启用自动暂停。设置启用自动暂停时暂停的首选项。",
"fastForwardModePlaybackRate": "Fast-forward Mode Playback Rate",
"copyOnMine": "将挖掘的字幕复制到剪贴板",
"corsHelperText": "请确保{{origin}}在您的AnkiConnect设置中的webCorsOriginalList中,如此<0>video</0>中所示。",
"customCssField": "CSS:{{styleKey}}",
"deck": "甲板",
"definitionField": "定义字段",
"extensionOverriddenBind": "已覆盖",
"extensionShortcut": "扩展快捷方式",
"imageBasedSubtitleScaleFactor": "基于图像的字幕比例因子",
"imageField": "图像字段",
"keyboardShortcuts": "键盘快捷键",
"language": "语言",
"maxImageHeight": "最大图像高度",
"maxImageWidth": "最大图像宽度",
"mining": "挖掘",
"miningHistoryStorageLimit": "挖掘历史存储限制",
"clickToMineDefaultAction": "Mining button default action",
"misc": "杂项",
"mp3Preference": "将音频重新编码为mp3(较慢)",
"noteType": "Anki卡牌类型",
"preCacheSubtitleDom": "预缓存字幕DOM",
"preCacheSubtitleDomHelperText": "如果启用,asbplayer将预呈现屏幕外文档中的字幕文本元素,并将这些元素重新用于字幕显示。这允许外部代码在显示字幕文本之前持续修改字幕文本。",
"recordingBind": "录音",
"rememberSubtitleOffset": "记住字幕偏移量",
"sentenceField": "句子字段",
"streamingVideo": "Streaming Video",
"styleKey": "样式键",
"styleValue": "样式值",
"sourceField": "源字段",
"subtitleAppearance": "字幕外观",
"subtitleBackgroundColor": "字幕背景颜色",
"subtitleBackgroundOpacity": "字幕背景不透明度",
"subtitleColor": "字幕颜色",
"subtitleFontFamily": "字幕字体系列",
"subtitleOutlineColor": "字幕轮廓线颜色",
"subtitleOutlineThickness": "字幕轮廓线厚度",
"subtitleShadowColor": "Subtitle Shadow Color",
"subtitleShadowThickness": "Subtitle Shadow Thickness",
"subtitleOutlineThicknessHelperText": "在字幕文本周围添加轮廓线。如果这会导致线条重叠,请尝试使用其他字体。",
"subtitlePositionOffset": "字幕位置从底部偏移",
"subtitleAlignment": "字幕对齐方式",
"subtitleAlignmentBottom": "底部",
"subtitleAlignmentTop": "顶部",
"subtitleRegexFilter": "字幕正则筛选器",
"subtitleRegexFilterTextReplacement": "字幕正则筛选器文本替换",
"subtitleSize": "字幕大小",
"subtitleThickness": "字幕字体厚度",
"surroundingSubtitlesCountRadius": "环绕字幕计数半径",
"surroundingSubtitlesTimeRadius": "环绕字幕时间半径",
"tags": "标签",
"tagsHelperText": "逗号分隔的字符串列表",
"theme": "主题",
"themeDark": "暗色主题",
"themeLight": "亮色主题",
"title": "设置",
"unlockLocalFonts": "Click to unlock font menu",
"unboundBind": "未绑定",
"urlField": "URL字段",
"wordField": "Word字段"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Click, hold, and drag to mine multiple subtitles"
}
}

1
asbplayer-extension/asbplayer.js

@ -0,0 +1 @@
(()=>{"use strict";const e=e=>{window.postMessage({sender:"asbplayer-extension-to-player",message:e})},s=new class{async get(e){return await chrome.storage.local.get(e)}async set(e){await chrome.storage.local.set(e)}};window.addEventListener("message",(async a=>{if(a.source!==window)return;const n=a.data;if("asbplayer"===n.sender||"asbplayerv2"===n.sender)switch(n.message.command){case"get-settings":const a=n.message;e({response:await s.get(a.keysAndDefaults),messageId:n.message.messageId});break;case"set-settings":const t=n.message;await s.set(t.settings),e({messageId:n.message.messageId});break;default:chrome.runtime.sendMessage(n)}})),chrome.runtime.onMessage.addListener(((e,s,a)=>{"asbplayer-extension-to-player"===e.sender&&window.postMessage(e)}));const a=chrome.runtime.getManifest();window.addEventListener("DOMContentLoaded",(async s=>{const n=await chrome.runtime.sendMessage({sender:"asbplayerv2",message:{command:"extension-commands"}});e({command:"version",version:a.version,extensionCommands:n})}))})();

BIN
asbplayer-extension/assets/icon128.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
asbplayer-extension/assets/icon16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
asbplayer-extension/assets/icon32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
asbplayer-extension/assets/icon48.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
asbplayer-extension/assets/image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

30
asbplayer-extension/background-page.html

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>asbplayer - Audio Capture</title>
</head>
<body style="background-color: #303030; margin: 0">
<div
id="root"
style="
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
position: absolute;
color: white;
font-family: 'Segoe UI', Arial, Meiryo, sans-serif;
font-size: 24px;
"
>
<div style="text-align: center">
<img src="assets/icon128.png" />
<div id="helper-text">This page is used by asbplayer to capture audio.</div>
</div>
</div>
<script src="background-page.js"></script>
</body>
</html>

2
asbplayer-extension/background-page.js

File diff suppressed because one or more lines are too long

1
asbplayer-extension/background-page.js.LICENSE.txt

@ -0,0 +1 @@
/*! https://mths.be/punycode v1.4.1 by @mathias */

2
asbplayer-extension/background.js

File diff suppressed because one or more lines are too long

1
asbplayer-extension/background.js.LICENSE.txt

@ -0,0 +1 @@
/*! https://mths.be/punycode v1.4.1 by @mathias */

12
asbplayer-extension/ftue-ui.html

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>asbplayer - Welcome</title>
</head>
<body style="background: rgba(0, 0, 0, 0)">
<div id="root"></div>
<script src="ftue-ui.js"></script>
</body>
</html>

2
asbplayer-extension/ftue-ui.js

File diff suppressed because one or more lines are too long

58
asbplayer-extension/ftue-ui.js.LICENSE.txt

@ -0,0 +1,58 @@
/*! https://mths.be/punycode v1.4.1 by @mathias */
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

118
asbplayer-extension/manifest.json

@ -0,0 +1,118 @@
{
"name": "asbplayer: Language-learning with subtitles",
"description": "__MSG_extensionDescription__",
"version": "1.0.0",
"manifest_version": 3,
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxmdAa3ymqAjLms43ympXqtyuJnC2bSYh70+5ZZmtyx/MsnGhTEdfbqtsp3BKxHbv0rPd49+Joacm1Shik5/mCppZ0h4I4ISMm983X01H6p/hfAzQYAcnvw/ZQNHAv1QgY9JiuyTBirCDoYB50Fxol/kI/0EviYXuX83KoYpjB0VGP/ssY9ocT//fQUbRmeLDJnciry8y6MduWXHzseOP99axQIjeVsNTE30L4fRN+ppX3aOkG/RFJNx0eI02qbLul3qw5dUuBK5GgMbYftwjHnDoOegnZYFr1sxRO1zsgmxdp/6du75RiDPRJOkPCz2GTrw4CX2FCywbDZlqaIpwqQIDAQAB",
"default_locale": "en",
"icons": {
"16": "assets/icon16.png",
"48": "assets/icon48.png",
"128": "assets/icon128.png"
},
"minimum_chrome_version": "114",
"permissions": ["tabs", "tabCapture", "activeTab", "storage", "contextMenus", "sidePanel"],
"action": {
"default_title": "asbplayer",
"default_popup": "popup-ui.html"
},
"options_ui": {
"page": "settings-ui.html",
"open_in_tab": true
},
"background": {
"service_worker": "background.js"
},
"side_panel": {
"default_path": "side-panel.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"exclude_globs": ["*://killergerbah.github.io/asbplayer*", "*://localhost:*/*"],
"js": ["video.js"],
"css": ["video.css"],
"all_frames": true,
"run_at": "document_idle"
},
{
"matches": ["<all_urls>"],
"exclude_globs": ["*://killergerbah.github.io/asbplayer*", "*://localhost:*/*"],
"js": ["page.js"],
"all_frames": true,
"run_at": "document_start"
},
{
"matches": ["*://killergerbah.github.io/asbplayer*", "*://localhost:*/*"],
"js": ["asbplayer.js"],
"all_frames": true,
"run_at": "document_start"
}
],
"commands": {
"copy-subtitle": {
"description": "__MSG_shortcutMineSubtitleDescription__"
},
"copy-subtitle-with-dialog": {
"suggested_key": {
"default": "Ctrl+Shift+X",
"mac": "MacCtrl+Shift+X"
},
"description": "__MSG_shortcutMineSubtitleAndOpenDialogDescription__"
},
"update-last-card": {
"suggested_key": {
"default": "Ctrl+Shift+U",
"mac": "MacCtrl+Shift+U"
},
"description": "__MSG_shortcutUpdateLastCardDescription__"
},
"toggle-video-select": {
"suggested_key": {
"default": "Ctrl+Shift+F",
"mac": "MacCtrl+Shift+F"
},
"description": "__MSG_shortcutSelectSubtitleTrackDescription__"
},
"take-screenshot": {
"suggested_key": {
"default": "Ctrl+Shift+V",
"mac": "MacCtrl+Shift+V"
},
"description": "__MSG_shortcutTakeScreenshotDescription__"
},
"toggle-recording": {
"description": "__MSG_shortcutToggleRecordingDescription__"
}
},
"web_accessible_resources": [
{
"resources": [
"assets/image.png",
"pages/netflix-page.js",
"pages/youtube-page.js",
"pages/tver-page.js",
"pages/bandai-channel-page.js",
"pages/amazon-prime-page.js",
"pages/hulu-page.js",
"pages/disney-plus-page.js",
"pages/unext-page.js",
"anki-ui.js",
"mp3-encoder-worker.js",
"pgs-parser-worker.js",
"video-data-sync-ui.js",
"video-select-ui.js",
"active-tab-permission-request-ui.js",
"app-ui.js",
"asbplayer-locales/de.json",
"asbplayer-locales/en.json",
"asbplayer-locales/es.json",
"asbplayer-locales/ja.json",
"asbplayer-locales/pl.json",
"asbplayer-locales/zh_CN.json",
"asbplayer-locales/pt_BR.json"
],
"matches": ["<all_urls>"]
}
]
}

1
asbplayer-extension/mp3-encoder-worker.js

File diff suppressed because one or more lines are too long

1
asbplayer-extension/page.js

@ -0,0 +1 @@
(()=>{"use strict";const t=JSON.parse('{"L":[{"host":"www\\\\.netflix\\\\.com","script":"netflix-page.js","path":"watch","autoSync":{"enabled":true}},{"host":"www\\\\.youtube\\\\.com","script":"youtube-page.js","path":"watch","autoSync":{"enabled":true}},{"host":"tver\\\\.jp","script":"tver-page.js","path":"episodes","autoSync":{"enabled":true}},{"host":"www\\\\.b-ch\\\\.com","script":"bandai-channel-page.js","path":"titles","autoSync":{"enabled":true}},{"host":"www\\\\.amazon\\\\..+","script":"amazon-prime-page.js","path":".*","autoSync":{"enabled":true,"videoSrc":"^blob:.+"},"ignore":{"class":"tst-video-overlay-player-html5","style":{"display":"none"}}},{"host":"www\\\\.hulu\\\\..+","script":"hulu-page.js","path":"watch","autoSync":{"enabled":true,"elementId":"content-video-player"}},{"host":"www\\\\.disneyplus\\\\..+","script":"disney-plus-page.js","path":"video","autoSync":{"enabled":true}},{"host":"video.unext.jp","script":"unext-page.js","path":"play","autoSync":{"enabled":false}}]}');class e{constructor(t,e){this.config=t,this.url=e}loadScripts(){const t=document.createElement("script");t.src=chrome.runtime.getURL(`pages/${this.config.script}`),t.onload=()=>t.remove(),(document.head||document.documentElement).appendChild(t)}shouldIgnore(t){if(void 0===this.config.ignore)return!1;if(void 0!==this.config.ignore.class&&t.classList.contains(this.config.ignore.class))return!0;if(void 0!==this.config.ignore.style)for(const e of Object.keys(this.config.ignore.style))if(t.style[e]===this.config.ignore.style[e])return!0;return!1}canAutoSync(t){return this.config.autoSync.enabled&&(void 0===this.config.autoSync.elementId||t.id===this.config.autoSync.elementId)&&(void 0===this.config.autoSync.videoSrc||new RegExp(this.config.autoSync.videoSrc).test(t.src))}isVideoPage(){return new RegExp(this.config.path).test(this.url.pathname)}}(function(){const n=new URL(window.location.href);for(const o of t.L)if(new RegExp(o.host).test(n.host))return new e(o,n)})()?.loadScripts()})();

76
asbplayer-extension/pages.json

@ -0,0 +1,76 @@
{
"pages": [
{
"host": "www\\.netflix\\.com",
"script": "netflix-page.js",
"path": "watch",
"autoSync": {
"enabled": true
}
},
{
"host": "www\\.youtube\\.com",
"script": "youtube-page.js",
"path": "watch",
"autoSync": {
"enabled": true
}
},
{
"host": "tver\\.jp",
"script": "tver-page.js",
"path": "episodes",
"autoSync": {
"enabled": true
}
},
{
"host": "www\\.b-ch\\.com",
"script": "bandai-channel-page.js",
"path": "titles",
"autoSync": {
"enabled": true
}
},
{
"host": "www\\.amazon\\..+",
"script": "amazon-prime-page.js",
"path": ".*",
"autoSync": {
"enabled": true,
"videoSrc": "^blob:.+"
},
"ignore": {
"class": "tst-video-overlay-player-html5",
"style": {
"display": "none"
}
}
},
{
"host": "www\\.hulu\\..+",
"script": "hulu-page.js",
"path": "watch",
"autoSync": {
"enabled": true,
"elementId": "content-video-player"
}
},
{
"host": "www\\.disneyplus\\..+",
"script": "disney-plus-page.js",
"path": "video",
"autoSync": {
"enabled": true
}
},
{
"host": "video.unext.jp",
"script": "unext-page.js",
"path": "play",
"autoSync": {
"enabled": false
}
}
]
}

1
asbplayer-extension/pages/amazon-prime-page.js

@ -0,0 +1 @@
(()=>{"use strict";var e,t={9612:(e,t,a)=>{function n(e,t){const a=e.lastIndexOf(".");let n=t;return-1!==a&&(n=e.substring(a+1)),n}function o({onJson:e,onRequest:t,waitForBasename:a}){setTimeout((()=>{const n={};let o="",s=!1;const i=JSON.parse;JSON.parse=function(){const t=i.apply(this,arguments);let a=!1,r=!1;return e(t,(e=>{const t=window.location.pathname;void 0===n[t]&&(n[t]=[]),void 0===n[t].find((t=>t.label===e.label&&t.language===e.language))&&(n[t].push(e),a=!0)}),(e=>{o=e,r=!0})),s&&(a||r)&&document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:o,subtitles:n[window.location.pathname]}})),t},document.addEventListener("asbplayer-get-synced-data",(async()=>{t?.((e=>{const t=window.location.pathname;void 0===n[t]&&(n[t]=[]),void 0===n[t].find((t=>t.label===e.label&&t.language===e.language))&&n[t].push(e)}),(e=>{o=e,s||document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:o,subtitles:void 0}}))}));const e=()=>(!a||""!==o)&&window.location.pathname in n;e()||await function(e,t=1e4){return new Promise((async(a,n)=>{e()&&a(!0);const o=Date.now();let s=!1;for(;!s&&Date.now()<o+t;)await new Promise((t=>{setTimeout((()=>{s=e(),t()}),1e3)}));a(s)}))}(e),document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:o,subtitles:n[window.location.pathname]??[]}})),function(){for(const e of Object.keys(n))e!==window.location.pathname&&delete n[e]}(),s=!0}),!1)}),0)}a.d(t,{NC:()=>o,YU:()=>n})}},a={};function n(e){var o=a[e];if(void 0!==o)return o.exports;var s=a[e]={exports:{}};return t[e](s,s.exports,n),s.exports}n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(0,(e=n(9612)).NC)({onJson:(t,a)=>{if(t?.subtitleUrls instanceof Array)for(const n of t.subtitleUrls)"string"==typeof t?.catalogMetadata?.catalog?.title&&"string"==typeof n.url&&"string"==typeof n.languageCode&&"string"==typeof n.displayName&&a({label:`${t.catalogMetadata.catalog.title} ${n.displayName}`,language:n.languageCode.toLowerCase(),url:n.url,extension:(0,e.YU)(n.url,"dfxp")})},waitForBasename:!1})})();

1
asbplayer-extension/pages/bandai-channel-page.js

@ -0,0 +1 @@
(()=>{"use strict";var e,t={9612:(e,t,n)=>{function o(e,t){const n=e.lastIndexOf(".");let o=t;return-1!==n&&(o=e.substring(n+1)),o}function a(e,t=1e4){return new Promise((async(n,o)=>{e()&&n(!0);const a=Date.now();let s=!1;for(;!s&&Date.now()<a+t;)await new Promise((t=>{setTimeout((()=>{s=e(),t()}),1e3)}));n(s)}))}function s({onJson:e,onRequest:t,waitForBasename:n}){setTimeout((()=>{const o={};let s="",i=!1;const r=JSON.parse;JSON.parse=function(){const t=r.apply(this,arguments);let n=!1,a=!1;return e(t,(e=>{const t=window.location.pathname;void 0===o[t]&&(o[t]=[]),void 0===o[t].find((t=>t.label===e.label&&t.language===e.language))&&(o[t].push(e),n=!0)}),(e=>{s=e,a=!0})),i&&(n||a)&&document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:s,subtitles:o[window.location.pathname]}})),t},document.addEventListener("asbplayer-get-synced-data",(async()=>{t?.((e=>{const t=window.location.pathname;void 0===o[t]&&(o[t]=[]),void 0===o[t].find((t=>t.label===e.label&&t.language===e.language))&&o[t].push(e)}),(e=>{s=e,i||document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:s,subtitles:void 0}}))}));const e=()=>(!n||""!==s)&&window.location.pathname in o;e()||await a(e),document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:s,subtitles:o[window.location.pathname]??[]}})),function(){for(const e of Object.keys(o))e!==window.location.pathname&&delete o[e]}(),i=!0}),!1)}),0)}n.d(t,{$l:()=>a,NC:()=>s,YU:()=>o})}},n={};function o(e){var a=n[e];if(void 0!==a)return a.exports;var s=n[e]={exports:{}};return t[e](s,s.exports,o),s.exports}o.d=(e,t)=>{for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(0,(e=o(9612)).NC)({onJson:(t,n,o)=>{let a;if(t?.bc?.text_tracks instanceof Array){for(const o of t.bc.text_tracks)if("subtitles"===o.kind&&"text/webvtt"===o.mime_type&&o.sources instanceof Array&&o.sources.length>0&&"string"==typeof o.sources[0].src&&"string"==typeof o.srclang){const t="string"==typeof o.label?`${o.srclang} - ${o?.label}`:o.srclang,a=o.sources[0].src.replace(/^http:\/\//,"https://");n({label:t,language:o.srclang.toLowerCase(),url:a,extension:(0,e.YU)(a,"vtt")})}"string"==typeof t.bc.name&&(a=t.bc.name,o(t.bc.name))}void 0===a&&"string"==typeof t?.bch?.episode_title&&(a=t.bch.episode_title,o(t.bch.episode_title))},onRequest:(t,n)=>{(0,e.$l)((()=>{const e=function(){const e=document.getElementById("bch-series-title"),t=document.getElementById("bch-story-title");if(e&&t&&e.textContent&&t.childNodes&&0!==t.childNodes.length)return`${e.textContent} ${t.childNodes[0].nodeValue}`}();return!!e&&(n(e),!0)}))||n(document.title)},waitForBasename:!0})})();

2
asbplayer-extension/pages/disney-plus-page.js

File diff suppressed because one or more lines are too long

1
asbplayer-extension/pages/disney-plus-page.js.LICENSE.txt

@ -0,0 +1 @@
/*! @name m3u8-parser @version 6.0.0 @license Apache-2.0 */

1
asbplayer-extension/pages/hulu-page.js

@ -0,0 +1 @@
(()=>{"use strict";var t,e={9612:(t,e,n)=>{function r(t,e){const n=t.lastIndexOf(".");let r=e;return-1!==n&&(r=t.substring(n+1)),r}n.d(e,{YU:()=>r})}},n={};function r(t){var o=n[t];if(void 0!==o)return o.exports;var s=n[t]={exports:{}};return e[t](s,s.exports,r),s.exports}r.d=(t,e)=>{for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),t=r(9612),setTimeout((()=>{let e,n,r,o;const s=JSON.stringify;JSON.stringify=function(a){const i=s.apply(this,arguments);var c,l;return"string"==typeof a?.content_eab_id&&"object"==typeof a?.playback&&null!==a?.playback&&(c=i,e?.abort(),r=new Promise(((n,r)=>{setTimeout((()=>{e?.abort(),e=new AbortController,fetch("https://play.hulu.com/v6/playlist",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:c,signal:e.signal}).then((t=>t.json())).then((e=>n(function(e){const n=[];if(r=e.transcripts_urls?.webvtt,"object"==typeof r&&!Array.isArray(r)&&null!==r){const r=e.transcripts_urls.webvtt;for(const e of Object.keys(r)){const o=r[e];"string"==typeof o&&void 0===n.find((t=>t.label===t.language))&&n.push({label:e,language:e.toLowerCase(),url:o,extension:(0,t.YU)(o,"vtt")})}}var r;return n}(e)))).catch(r)}),0)})),l=a.content_eab_id,n?.abort(),o=new Promise(((t,e)=>{setTimeout((()=>{n?.abort(),n=new AbortController,fetch(`https://discover.hulu.com/content/v3/browse/upnext?current_eab=${encodeURIComponent(l)}&referral_host=www.hulu.com&schema=4`,{signal:n.signal}).then((t=>t.json())).then((e=>t(function(t){if(t?.items instanceof Array&&t.items.length>0){const e=t.items[0];return e.series_name&&e.season_short_display_name&&e.number&&e.name?`${e.series_name}.${e.season_short_display_name}.E${e.number} - ${e.name}`:e.name??""}return""}(e)))).catch(e)}),0)}))),i},document.addEventListener("asbplayer-get-synced-data",(async()=>{let t="",e=[],n="";try{void 0!==o&&(t=await o,o=void 0),void 0!==r&&(e=await r,r=void 0)}catch(t){n=t instanceof Error?t.message:String(t)}const s={error:n,basename:t,subtitles:e};document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:s}))}),!1)}),0)})();

1
asbplayer-extension/pages/netflix-page.js

@ -0,0 +1 @@
(()=>{"use strict";setTimeout((()=>{const e="webvtt-lssdh-ios8",t=new RegExp("manifest|licensedManifest"),n=new Map;function s(){if("undefined"!=typeof netflix)return netflix?.appContext?.state?.playerApp?.getAPI?.()}function a(){return s()?.videoPlayer}function i(){const e=a();if(e){const t=e.getAllPlayerSessionIds?.()||[];if(0===t.length)return void console.error("No Netflix player session IDs");const n=t[t.length-1];return e.getVideoPlayerBySessionId?.(n)}console.error("Missing netflix global")}function r(t){if(t.isForcedNarrative||t.isNoneTrack||!t.cdnlist?.length||!t.ttDownloadables)return;const n=t.ttDownloadables[e];return n?.downloadUrls?n.downloadUrls[t.cdnlist.find((e=>n.downloadUrls[e.id]))?.id]:void 0}function o(t){if(t.isForcedNarrative||t.isNoneTrack||!t.ttDownloadables)return;const n=t.ttDownloadables[e];return n?.urls&&0!==n.urls.length?n.urls[0].url:void 0}async function d(e,t){if(t<=0)return`${e}`;const[n,a]=function(e){const t=s()?.getVideoMetadataByVideoId?.(e)?.getCurrentVideo?.(),n=t?.getTitle?.();if("string"!=typeof n)return[`${e}`,!0];let a=n;if(!0===t?.isEpisodic?.()){const e=`${t?.getSeason()?._season?.seq}`.padStart(2,"0"),n=`${t?.getEpisodeNumber?.()}`.padStart(2,"0"),s=t?.getEpisodeTitle?.();a+=` S${e}E${n} ${s}`}return[a,!1]}(e);return a?(await new Promise((e=>setTimeout(e,1e3))),await d(e,--t)):n}document.addEventListener("asbplayer-netflix-seek",(e=>{i()?.seek(e.detail)})),document.addEventListener("asbplayer-netflix-play",(()=>{i()?.play()})),document.addEventListener("asbplayer-netflix-pause",(()=>{i()?.pause()})),document.addEventListener("asbplayer-get-synced-data",(async()=>{const e={error:"",basename:"",subtitles:[]},t=i(),s=t?.getMovieId();if(!t||!s)return e.error="Netflix Player or Title Id not found...",document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:e}));e.basename=await d(s,5);const a=n.get(s)||new Map;e.subtitles=t.getTimedTextTrackList().filter((e=>a.has(e.trackId))).map((e=>({label:`${e.bcp47} - ${e.displayName}${"CLOSEDCAPTIONS"===e.rawTrackType?" [CC]":""}`,language:e.bcp47.toLowerCase(),url:a.get(e.trackId),extension:"nfvtt"}))),document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:e}))}),!1);const l=JSON.stringify;JSON.stringify=function(n){if("string"==typeof n?.url&&-1<n.url.search(t))for(let t of Object.values(n))t?.profiles?.unshift(e);return l.apply(this,arguments)};const c=JSON.parse;JSON.parse=function(){const e=c.apply(this,arguments);return e?.result?.movieId&&function(e){const t=e.timedtexttracks||[];for(const s of t){const t=r(s)??o(s);t&&(n.has(e.movieId)||n.set(e.movieId,new Map),n.get(e.movieId).set(s.new_track_id,t))}}(e.result),e},document.addEventListener("asbplayer-query-netflix",(()=>{document.dispatchEvent(new CustomEvent("asbplayer-netflix-enabled",{detail:void 0!==a()}))}))}),0)})();

1
asbplayer-extension/pages/tver-page.js

@ -0,0 +1 @@
(()=>{"use strict";var e,t={9612:(e,t,n)=>{function a(e,t){const n=e.lastIndexOf(".");let a=t;return-1!==n&&(a=e.substring(n+1)),a}function o({onJson:e,onRequest:t,waitForBasename:n}){setTimeout((()=>{const a={};let o="",s=!1;const r=JSON.parse;JSON.parse=function(){const t=r.apply(this,arguments);let n=!1,i=!1;return e(t,(e=>{const t=window.location.pathname;void 0===a[t]&&(a[t]=[]),void 0===a[t].find((t=>t.label===e.label&&t.language===e.language))&&(a[t].push(e),n=!0)}),(e=>{o=e,i=!0})),s&&(n||i)&&document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:o,subtitles:a[window.location.pathname]}})),t},document.addEventListener("asbplayer-get-synced-data",(async()=>{t?.((e=>{const t=window.location.pathname;void 0===a[t]&&(a[t]=[]),void 0===a[t].find((t=>t.label===e.label&&t.language===e.language))&&a[t].push(e)}),(e=>{o=e,s||document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:o,subtitles:void 0}}))}));const e=()=>(!n||""!==o)&&window.location.pathname in a;e()||await function(e,t=1e4){return new Promise((async(n,a)=>{e()&&n(!0);const o=Date.now();let s=!1;for(;!s&&Date.now()<o+t;)await new Promise((t=>{setTimeout((()=>{s=e(),t()}),1e3)}));n(s)}))}(e),document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:o,subtitles:a[window.location.pathname]??[]}})),function(){for(const e of Object.keys(a))e!==window.location.pathname&&delete a[e]}(),s=!0}),!1)}),0)}n.d(t,{NC:()=>o,YU:()=>a})}},n={};function a(e){var o=n[e];if(void 0!==o)return o.exports;var s=n[e]={exports:{}};return t[e](s,s.exports,a),s.exports}a.d=(e,t)=>{for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(0,(e=a(9612)).NC)({onJson:(t,n,a)=>{if(t?.text_tracks instanceof Array){for(const a of t.text_tracks)if("captions"===a.kind&&"text/webvtt"===a.mime_type&&a.sources instanceof Array&&a.sources.length>0&&"string"==typeof a.sources[0].src&&"string"==typeof a.srclang){const t="string"==typeof a.label?`${a.srclang} - ${a?.label}`:a.srclang,o=a.srclang.toLowerCase(),s=a.sources[0].src;n({label:t,language:o,url:s.replace(/^http:\/\//,"https://"),extension:(0,e.YU)(s,"vtt")})}"string"==typeof t?.name&&a(t?.name)}},waitForBasename:!0})})();

1
asbplayer-extension/pages/unext-page.js

@ -0,0 +1 @@
(()=>{"use strict";var e,t={9612:(e,t,n)=>{function o(e,t=1e4){return new Promise((async(n,o)=>{e()&&n(!0);const r=Date.now();let s=!1;for(;!s&&Date.now()<r+t;)await new Promise((t=>{setTimeout((()=>{s=e(),t()}),1e3)}));n(s)}))}n.d(t,{$l:()=>o})}},n={};function o(e){var r=n[e];if(void 0!==r)return r.exports;var s=n[e]={exports:{}};return t[e](s,s.exports,o),s.exports}o.d=(e,t)=>{for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),e=o(9612),document.addEventListener("asbplayer-get-synced-data",(async()=>{let t="";await(0,e.$l)((()=>{const e=document.querySelectorAll('div[class^="Header__TitleContainer"]'),n=[],o=[];for(let t=0;t<e.length;++t)o.push(e[t]);for(;o.length>0;){const e=o.shift();if(void 0===e)break;if(0!==e.childNodes.length)for(let t=0;t<e.childNodes.length;++t){const n=e.childNodes[t];o.push(n)}else{const t=e.textContent;null!==t&&n.push(t)}}return n.length>0&&(t=n.join(" "),!0)})),document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:{error:"",basename:t,subtitles:[]}}))}))})();

1
asbplayer-extension/pages/util.js

@ -0,0 +1 @@
(()=>{"use strict"})();

1
asbplayer-extension/pages/youtube-page.js

@ -0,0 +1 @@
(()=>{"use strict";document.addEventListener("asbplayer-get-synced-data",(async()=>{const e={error:"",basename:"",subtitles:[]};try{const t=await fetch(window.location.href).then((e=>{if(!e.ok)throw new Error(`YT Context Retrieval failed with Status ${e.status}/${e.statusText}...`);return e.text()})).then((e=>(new window.DOMParser).parseFromString(e,"text/html"))).then((e=>{const t=e.body.querySelectorAll("script");let n;for(let e=0;e<t.length;++e){const r=t[e];if(r.textContent?.includes("ytInitialPlayerResponse")){n=r;break}}if(!n)throw new Error("YT Player Context not found...");return new Function(`${n.textContent}; return ytInitialPlayerResponse;`)()}));if(!t)throw new Error("YT Player Context not found...");e.basename=t.videoDetails?.title||document.title,e.subtitles=(t?.captions?.playerCaptionsTracklistRenderer?.captionTracks||[]).map((e=>({label:`${e.languageCode} - ${e.name?.simpleText}`,language:e.languageCode.toLowerCase(),url:e.baseUrl,extension:"ytxml"})))}catch(t){t instanceof Error?e.error=t.message:e.error=String(t)}finally{document.dispatchEvent(new CustomEvent("asbplayer-synced-data",{detail:e}))}}),!1)})();

1
asbplayer-extension/pgs-parser-worker.js

File diff suppressed because one or more lines are too long

12
asbplayer-extension/popup-ui.html

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>asbplayer - Popup</title>
</head>
<body style="background: rgba(0,0,0,0)">
<div id="root"></div>
<script src="popup-ui.js"></script>
</body>
</html>

2
asbplayer-extension/popup-ui.js

File diff suppressed because one or more lines are too long

88
asbplayer-extension/popup-ui.js.LICENSE.txt

@ -0,0 +1,88 @@
/*! https://mths.be/punycode v1.4.1 by @mathias */
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license Material-UI v4.11.2
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license Material-UI v4.12.1
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**!
* hotkeys-js v3.10.0
* A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.
*
* Copyright (c) 2022 kenny wong <[email protected]>
* http://jaywcjlove.github.io/hotkeys
* Licensed under the MIT license
*/

12
asbplayer-extension/settings-ui.html

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>asbplayer - Settings</title>
</head>
<body>
<div id="root"></div>
<script src="settings-ui.js"></script>
</body>
</html>

2
asbplayer-extension/settings-ui.js

File diff suppressed because one or more lines are too long

88
asbplayer-extension/settings-ui.js.LICENSE.txt

@ -0,0 +1,88 @@
/*! https://mths.be/punycode v1.4.1 by @mathias */
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license Material-UI v4.11.2
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license Material-UI v4.12.1
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**!
* hotkeys-js v3.10.0
* A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.
*
* Copyright (c) 2022 kenny wong <[email protected]>
* http://jaywcjlove.github.io/hotkeys
* Licensed under the MIT license
*/

13
asbplayer-extension/side-panel.html

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en" style="width: 100%; height: 100%">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>asbplayer</title>
</head>
<body style="width: 100%; height: 100%">
<div id="root" style="width: 100%; height: 100%"></div>
<script src="side-panel.js"></script>
<script src="asbplayer.js"></script>
</body>
</html>

2
asbplayer-extension/side-panel.js

File diff suppressed because one or more lines are too long

67
asbplayer-extension/side-panel.js.LICENSE.txt

@ -0,0 +1,67 @@
/*! https://mths.be/punycode v1.4.1 by @mathias */
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**!
* hotkeys-js v3.10.0
* A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.
*
* Copyright (c) 2022 kenny wong <[email protected]>
* http://jaywcjlove.github.io/hotkeys
* Licensed under the MIT license
*/

2
asbplayer-extension/video-data-sync-ui.js

File diff suppressed because one or more lines are too long

77
asbplayer-extension/video-data-sync-ui.js.LICENSE.txt

@ -0,0 +1,77 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license Material-UI v4.11.2
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license Material-UI v4.12.1
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

2
asbplayer-extension/video-select-ui.js

File diff suppressed because one or more lines are too long

56
asbplayer-extension/video-select-ui.js.LICENSE.txt

@ -0,0 +1,56 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

145
asbplayer-extension/video.css

@ -0,0 +1,145 @@
.asbplayer-subtitles-container-bottom {
position: absolute;
left: 50%;
transform: translate(-50%, -100%);
display: inline-block;
z-index: 2147483647;
}
.asbplayer-subtitles-container-top {
position: absolute;
left: 50%;
transform: translate(-50%);
display: inline-block;
z-index: 2147483647;
}
.asbplayer-subtitles {
text-align: center !important;
color: white;
font-size: 24px;
padding-left: 10px;
padding-right: 10px;
user-select: text !important;
cursor: text !important;
line-height: normal !important;
white-space: pre-wrap !important;
}
.asbplayer-notification-container-bottom {
position: absolute !important;
left: 50%;
transform: translate(-50%, -100%);
display: inline-block;
z-index: 2147483647 !important;
}
.asbplayer-notification-container-top {
position: absolute !important;
left: 50%;
transform: translate(-50%);
display: inline-block;
z-index: 2147483647 !important;
}
.asbplayer-notification {
text-align: center !important;
color: white;
text-shadow: 0 0 2px black, 0 0 2px black, 0 0 2px black, 0 0 2px black;
font-size: 24px;
padding-left: 10px;
padding-right: 10px;
line-height: normal !important;
white-space: pre-wrap !important;
user-select: none;
pointer-events: none;
}
.asbplayer-fullscreen-subtitles {
text-align: center !important;
color: white;
text-shadow: 0 0 2px black, 0 0 2px black, 0 0 2px black, 0 0 2px black;
font-size: 36px;
padding-left: 10px;
padding-right: 10px;
user-select: text !important;
cursor: text !important;
line-height: normal !important;
white-space: pre-wrap !important;
}
.asbplayer-ui-frame {
position: fixed !important;
top: 0 !important;
left: 0 !important;
visibility: visible !important;
width: 100% !important;
height: 100% !important;
z-index: 2147483647 !important;
border: 0;
}
.asbplayer-hide {
display: none !important;
}
.asbplayer-drag-zone-initial {
position: absolute;
pointer-events: none;
z-index: 2147483647;
}
.asbplayer-drag-zone-dragging {
pointer-events: all;
}
.asbplayer-image {
position: relative;
pointer-events: none;
}
.asbplayer-image-fade-in {
animation-duration: 0.2s;
animation-name: asbplayer-fade-in;
}
@keyframes asbplayer-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.asbplayer-image-container {
position: absolute;
z-index: 2147483647;
background-color: rgba(0, 0, 0, 0.5);
}
.asbplayer-drag-image {
pointer-events: none;
}
.asbplayer-mouse-over-image {
position: absolute;
z-index: 2147483647;
}
.asbplayer-mouse-over-image {
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: 0.2s;
}
.asbplayer-mouse-over-image:hover {
opacity: 1;
}
.asbplayer-offscreen {
position: fixed !important;
left: 100% !important;
top: 100% !important;
}

2
asbplayer-extension/video.js

File diff suppressed because one or more lines are too long

12
asbplayer-extension/video.js.LICENSE.txt

@ -0,0 +1,12 @@
/*! @name m3u8-parser @version 6.0.0 @license Apache-2.0 */
/*! https://mths.be/punycode v1.4.1 by @mathias */
/**!
* hotkeys-js v3.10.0
* A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.
*
* Copyright (c) 2022 kenny wong <[email protected]>
* http://jaywcjlove.github.io/hotkeys
* Licensed under the MIT license
*/

14
google-lens-search/background.js

@ -0,0 +1,14 @@
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: "searchWithLens",
title: "Search Image with Google Lens",
contexts: ["image"]
});
});
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === "searchWithLens") {
const url = `https://lens.google.com/uploadbyurl?url=${encodeURIComponent(info.srcUrl)}`;
chrome.tabs.create({ url });
}
});

BIN
google-lens-search/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

13
google-lens-search/manifest.json

@ -0,0 +1,13 @@
{
"manifest_version": 3,
"name": "Search Image with Google Lens",
"version": "1.0",
"description": "Adds a context menu item to search an image with Google Lens",
"permissions": ["contextMenus", "activeTab"],
"background": {
"service_worker": "background.js"
},
"icons": {
"48": "icon.png"
}
}

BIN
image-saver/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

39
image-saver/main.js

@ -0,0 +1,39 @@
function saveImageFromUrl(info, tab) {
const url = info.srcUrl;
const data = new URLSearchParams({
url: url
});
fetch("https://images.gregoryleeman.com/upload-url", {
method: "POST",
body: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
})
.then(response => {
if (!response.ok) {
console.error("Server responded with a non-OK status.");
return response.text().then(text => {
console.error("Server response:", text);
throw new Error("Server error");
});
} else {
console.log("Image successfully uploaded.");
}
})
.catch(error => {
console.error('Fetch error:', error.message);
});
}
chrome.contextMenus.create({
id: "save-image",
title: "Save Image",
contexts: ["image"]
});
chrome.contextMenus.onClicked.addListener(function(info, tab) {
saveImageFromUrl(info, tab);
});

19
image-saver/manifest.json

@ -0,0 +1,19 @@
{
"name": "Image Saver",
"description": "Save an image on the web to my server.",
"version": "1.0.0",
"manifest_version": 3,
"permissions": [
"contextMenus",
"notifications"
],
"host_permissions": [
"https://*/"
],
"background": {
"service_worker": "main.js"
},
"icons": {
"48": "icon.png"
}
}

BIN
media-helper/.DS_Store

Binary file not shown.

41
media-helper/background.js

@ -0,0 +1,41 @@
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
const data = message.data;
data.url = message.url;
if (message.action === 'saveMedia') {
fetch('https://media.gregoryleeman.com/api/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then((response) => response.json())
.then((responseData) => {
console.log('Success:', responseData);
sendResponse({ success: true, responseData });
})
.catch((error) => {
console.error('Error:', error);
sendResponse({ success: false, error });
});
return true; // Keep the message channel open for async response
} else if ( message.action == 'checkMedia' ) {
fetch('https://media.gregoryleeman.com/api/items/check?url=' + encodeURIComponent(data.url), {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => response.json())
.then((responseData) => {
console.log('Success:', responseData);
sendResponse({ success: true, responseData });
})
.catch((error) => {
console.error('Error:', error);
sendResponse({ success: false, error });
});
return true; // Keep the message channel open for async response
}
});

143
media-helper/element.js

@ -0,0 +1,143 @@
// element.js
export class Element {
constructor(elementOrTag) {
if (typeof elementOrTag === 'string') {
this.element = document.createElement(elementOrTag);
} else if (elementOrTag instanceof Element) {
return elementOrTag;
} else if (elementOrTag instanceof HTMLElement) {
this.element = elementOrTag;
} else {
throw new Error("Element expects a tag name or an HTMLElement.");
}
return this;
}
setProperty(propertyName, value) {
this.element[propertyName] = value;
return this;
}
getProperty(propertyName) {
return this.element[propertyName];
}
setText(text) {
this.setProperty('innerText', text);
return this;
}
getText() {
return this.getProperty('innerText');
}
getValue() {
return this.element.value;
}
setInnerHtml(html) {
this.setProperty('innerHTML', html);
return this;
}
getHtml() {
return this.getProperty('innerHTML');
}
setAttribute(attributeName, value) {
this.element.setAttribute(attributeName, value);
return this;
}
removeAttribute(attributeName) {
this.element.removeAttribute(attributeName);
return this;
}
setId(id) {
this.element.id = id;
return this;
}
addClass(...classNames) {
if (classNames.length === 1 && classNames[0] instanceof Array) {
classNames = classNames[0];
classNames.forEach(className => this.element.classList.add(className));
} else {
this.element.classList.add(...classNames);
}
return this;
}
removeClass(...className) {
if (className.length === 1 && className[0] instanceof Array) {
className = className[0];
className.forEach(c => this.element.classList.remove(c));
} else {
console.log(className);
this.element.classList.remove(...className);
}
return this;
}
appendChild(child) {
if (child instanceof Array) {
child.forEach(c => this.appendChild(c));
} else if (child instanceof Element) {
this.element.appendChild(child.element);
} else if (child instanceof HTMLElement) {
this.element.appendChild(child);
} else if (typeof child === 'function') {
this.element.appendChild(child());
} else {
throw new Error('appendChild expects an Element, HTMLElement, or function.');
}
return this;
}
addEventListener(eventType, listener, options) {
this.element.addEventListener(eventType, listener, options);
return this;
}
appendTo(parent) {
if (parent instanceof Element) {
parent.get().appendChild(this.element);
} else if (parent instanceof HTMLElement) {
parent.appendChild(this.element);
}
return this;
}
prependTo(parent) {
if (parent instanceof Element) {
parent.get().prepend(this.element);
} else if (parent instanceof HTMLElement) {
parent.prepend(this.element);
}
return this;
}
classList() {
return this.element.classList;
}
get() {
return this.element;
}
remove() {
this.element.remove();
}
clear() {
this.element.innerHTML = '';
return this;
}
}

BIN
media-helper/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

0
media-helper/icon.svg

10
media-helper/index.html

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en" style="width: 260px; height: 120px;">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<script type="module" src="script.js"></script>
</body>
</html>

31
media-helper/manifest.json

@ -0,0 +1,31 @@
{
"manifest_version": 3,
"author": "Gregory Leeman",
"background": {
"service_worker": "background.js"
},
"action": {
"default_icon": "icon.png",
"default_popup": "index.html"
},
"icons": {
"128": "icon.png"
},
"description": "Save media",
"name": "Media Helper",
"permissions": [
"contextMenus",
"clipboardWrite",
"activeTab",
"scripting",
"tabs"
],
"version": "1.0",
"web_accessible_resources": [
{
"resources": [ "style.css" ],
"matches": [ "<all_urls>" ]
}
],
"host_permissions": ["https://media.gregoryleeman.com/*"]
}

1
media-helper/node_modules/.bin/autoprefixer

@ -0,0 +1 @@
../autoprefixer/bin/autoprefixer

1
media-helper/node_modules/.bin/browserslist

@ -0,0 +1 @@
../browserslist/cli.js

1
media-helper/node_modules/.bin/cssesc

@ -0,0 +1 @@
../cssesc/bin/cssesc

1
media-helper/node_modules/.bin/glob

@ -0,0 +1 @@
../glob/dist/esm/bin.mjs

1
media-helper/node_modules/.bin/jiti

@ -0,0 +1 @@
../jiti/bin/jiti.js

1
media-helper/node_modules/.bin/nanoid

@ -0,0 +1 @@
../nanoid/bin/nanoid.cjs

1
media-helper/node_modules/.bin/node-which

@ -0,0 +1 @@
../which/bin/node-which

1
media-helper/node_modules/.bin/resolve

@ -0,0 +1 @@
../resolve/bin/resolve

1
media-helper/node_modules/.bin/sucrase

@ -0,0 +1 @@
../sucrase/bin/sucrase

1
media-helper/node_modules/.bin/sucrase-node

@ -0,0 +1 @@
../sucrase/bin/sucrase-node

1
media-helper/node_modules/.bin/tailwind

@ -0,0 +1 @@
../tailwindcss/lib/cli.js

1
media-helper/node_modules/.bin/tailwindcss

@ -0,0 +1 @@
../tailwindcss/lib/cli.js

1
media-helper/node_modules/.bin/update-browserslist-db

@ -0,0 +1 @@
../update-browserslist-db/cli.js

1
media-helper/node_modules/.bin/yaml

@ -0,0 +1 @@
../yaml/bin.mjs

1521
media-helper/node_modules/.package-lock.json

File diff suppressed because it is too large

128
media-helper/node_modules/@alloc/quick-lru/index.d.ts

@ -0,0 +1,128 @@
declare namespace QuickLRU {
interface Options<KeyType, ValueType> {
/**
The maximum number of milliseconds an item should remain in the cache.
@default Infinity
By default, `maxAge` will be `Infinity`, which means that items will never expire.
Lazy expiration upon the next write or read call.
Individual expiration of an item can be specified by the `set(key, value, maxAge)` method.
*/
readonly maxAge?: number;
/**
The maximum number of items before evicting the least recently used items.
*/
readonly maxSize: number;
/**
Called right before an item is evicted from the cache.
Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`).
*/
onEviction?: (key: KeyType, value: ValueType) => void;
}
}
declare class QuickLRU<KeyType, ValueType>
implements Iterable<[KeyType, ValueType]> {
/**
The stored item count.
*/
readonly size: number;
/**
Simple ["Least Recently Used" (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29).
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
@example
```
import QuickLRU = require('quick-lru');
const lru = new QuickLRU({maxSize: 1000});
lru.set('🦄', '🌈');
lru.has('🦄');
//=> true
lru.get('🦄');
//=> '🌈'
```
*/
constructor(options: QuickLRU.Options<KeyType, ValueType>);
[Symbol.iterator](): IterableIterator<[KeyType, ValueType]>;
/**
Set an item. Returns the instance.
Individual expiration of an item can be specified with the `maxAge` option. If not specified, the global `maxAge` value will be used in case it is specified in the constructor, otherwise the item will never expire.
@returns The list instance.
*/
set(key: KeyType, value: ValueType, options?: {maxAge?: number}): this;
/**
Get an item.
@returns The stored item or `undefined`.
*/
get(key: KeyType): ValueType | undefined;
/**
Check if an item exists.
*/
has(key: KeyType): boolean;
/**
Get an item without marking it as recently used.
@returns The stored item or `undefined`.
*/
peek(key: KeyType): ValueType | undefined;
/**
Delete an item.
@returns `true` if the item is removed or `false` if the item doesn't exist.
*/
delete(key: KeyType): boolean;
/**
Delete all items.
*/
clear(): void;
/**
Update the `maxSize` in-place, discarding items as necessary. Insertion order is mostly preserved, though this is not a strong guarantee.
Useful for on-the-fly tuning of cache sizes in live systems.
*/
resize(maxSize: number): void;
/**
Iterable for all the keys.
*/
keys(): IterableIterator<KeyType>;
/**
Iterable for all the values.
*/
values(): IterableIterator<ValueType>;
/**
Iterable for all entries, starting with the oldest (ascending in recency).
*/
entriesAscending(): IterableIterator<[KeyType, ValueType]>;
/**
Iterable for all entries, starting with the newest (descending in recency).
*/
entriesDescending(): IterableIterator<[KeyType, ValueType]>;
}
export = QuickLRU;

263
media-helper/node_modules/@alloc/quick-lru/index.js

@ -0,0 +1,263 @@
'use strict';
class QuickLRU {
constructor(options = {}) {
if (!(options.maxSize && options.maxSize > 0)) {
throw new TypeError('`maxSize` must be a number greater than 0');
}
if (typeof options.maxAge === 'number' && options.maxAge === 0) {
throw new TypeError('`maxAge` must be a number greater than 0');
}
this.maxSize = options.maxSize;
this.maxAge = options.maxAge || Infinity;
this.onEviction = options.onEviction;
this.cache = new Map();
this.oldCache = new Map();
this._size = 0;
}
_emitEvictions(cache) {
if (typeof this.onEviction !== 'function') {
return;
}
for (const [key, item] of cache) {
this.onEviction(key, item.value);
}
}
_deleteIfExpired(key, item) {
if (typeof item.expiry === 'number' && item.expiry <= Date.now()) {
if (typeof this.onEviction === 'function') {
this.onEviction(key, item.value);
}
return this.delete(key);
}
return false;
}
_getOrDeleteIfExpired(key, item) {
const deleted = this._deleteIfExpired(key, item);
if (deleted === false) {
return item.value;
}
}
_getItemValue(key, item) {
return item.expiry ? this._getOrDeleteIfExpired(key, item) : item.value;
}
_peek(key, cache) {
const item = cache.get(key);
return this._getItemValue(key, item);
}
_set(key, value) {
this.cache.set(key, value);
this._size++;
if (this._size >= this.maxSize) {
this._size = 0;
this._emitEvictions(this.oldCache);
this.oldCache = this.cache;
this.cache = new Map();
}
}
_moveToRecent(key, item) {
this.oldCache.delete(key);
this._set(key, item);
}
* _entriesAscending() {
for (const item of this.oldCache) {
const [key, value] = item;
if (!this.cache.has(key)) {
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield item;
}
}
}
for (const item of this.cache) {
const [key, value] = item;
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield item;
}
}
}
get(key) {
if (this.cache.has(key)) {
const item = this.cache.get(key);
return this._getItemValue(key, item);
}
if (this.oldCache.has(key)) {
const item = this.oldCache.get(key);
if (this._deleteIfExpired(key, item) === false) {
this._moveToRecent(key, item);
return item.value;
}
}
}
set(key, value, {maxAge = this.maxAge === Infinity ? undefined : Date.now() + this.maxAge} = {}) {
if (this.cache.has(key)) {
this.cache.set(key, {
value,
maxAge
});
} else {
this._set(key, {value, expiry: maxAge});
}
}
has(key) {
if (this.cache.has(key)) {
return !this._deleteIfExpired(key, this.cache.get(key));
}
if (this.oldCache.has(key)) {
return !this._deleteIfExpired(key, this.oldCache.get(key));
}
return false;
}
peek(key) {
if (this.cache.has(key)) {
return this._peek(key, this.cache);
}
if (this.oldCache.has(key)) {
return this._peek(key, this.oldCache);
}
}
delete(key) {
const deleted = this.cache.delete(key);
if (deleted) {
this._size--;
}
return this.oldCache.delete(key) || deleted;
}
clear() {
this.cache.clear();
this.oldCache.clear();
this._size = 0;
}
resize(newSize) {
if (!(newSize && newSize > 0)) {
throw new TypeError('`maxSize` must be a number greater than 0');
}
const items = [...this._entriesAscending()];
const removeCount = items.length - newSize;
if (removeCount < 0) {
this.cache = new Map(items);
this.oldCache = new Map();
this._size = items.length;
} else {
if (removeCount > 0) {
this._emitEvictions(items.slice(0, removeCount));
}
this.oldCache = new Map(items.slice(removeCount));
this.cache = new Map();
this._size = 0;
}
this.maxSize = newSize;
}
* keys() {
for (const [key] of this) {
yield key;
}
}
* values() {
for (const [, value] of this) {
yield value;
}
}
* [Symbol.iterator]() {
for (const item of this.cache) {
const [key, value] = item;
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield [key, value.value];
}
}
for (const item of this.oldCache) {
const [key, value] = item;
if (!this.cache.has(key)) {
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield [key, value.value];
}
}
}
}
* entriesDescending() {
let items = [...this.cache];
for (let i = items.length - 1; i >= 0; --i) {
const item = items[i];
const [key, value] = item;
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield [key, value.value];
}
}
items = [...this.oldCache];
for (let i = items.length - 1; i >= 0; --i) {
const item = items[i];
const [key, value] = item;
if (!this.cache.has(key)) {
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield [key, value.value];
}
}
}
}
* entriesAscending() {
for (const [key, value] of this._entriesAscending()) {
yield [key, value.value];
}
}
get size() {
if (!this._size) {
return this.oldCache.size;
}
let oldCacheSize = 0;
for (const key of this.oldCache.keys()) {
if (!this.cache.has(key)) {
oldCacheSize++;
}
}
return Math.min(this._size + oldCacheSize, this.maxSize);
}
}
module.exports = QuickLRU;

9
media-helper/node_modules/@alloc/quick-lru/license

@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <[email protected]> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

43
media-helper/node_modules/@alloc/quick-lru/package.json

@ -0,0 +1,43 @@
{
"name": "@alloc/quick-lru",
"version": "5.2.0",
"description": "Simple “Least Recently Used” (LRU) cache",
"license": "MIT",
"repository": "sindresorhus/quick-lru",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "[email protected]",
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=10"
},
"scripts": {
"test": "xo && nyc ava && tsd"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"lru",
"quick",
"cache",
"caching",
"least",
"recently",
"used",
"fast",
"map",
"hash",
"buffer"
],
"devDependencies": {
"ava": "^2.0.0",
"coveralls": "^3.0.3",
"nyc": "^15.0.0",
"tsd": "^0.11.0",
"xo": "^0.26.0"
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save