Youtube double language subtitle / Youtube 双语字幕

Youtube double language subtitle / Youtube 双语字幕. 如果不能自动加载,请关闭字幕再次打开即可。默认语言为浏览器首选语言。

目前為 2020-06-06 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Youtube double language subtitle / Youtube 双语字幕
  3. // @version 1.6.2
  4. // @description Youtube double language subtitle / Youtube 双语字幕. 如果不能自动加载,请关闭字幕再次打开即可。默认语言为浏览器首选语言。
  5. // @author Coink
  6. // @match *://www.youtube.com/watch?v=*
  7. // @match *://www.youtube.com
  8. // @match *://www.youtube.com/*
  9. // @require https://unpkg.com/ajax-hook@2.0.2/dist/ajaxhook.min.js
  10. // @grant none
  11. // @namespace https://github.com/CoinkWang/Y2BDoubleSubs
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. let localeLang = navigator.language ? navigator.language : 'en'
  16. // localeLang = 'zh' // uncomment this line to define the language you wish here
  17. ah.proxy({
  18. onRequest: (config, handler) => {
  19. handler.next(config);
  20. },
  21. onResponse: (response, handler) => {
  22. if (response.config.url.includes('/api/timedtext') && !response.config.url.includes('&translate_h00ked')){
  23. let xhr = new XMLHttpRequest();
  24. // Use RegExp to clean '&tlang=...' in our xhr request params while using Y2B auto translate.
  25. let reg = new RegExp("(^|[&?])tlang=([^&]*)",'g');
  26. xhr.open('GET', `${response.config.url.replace(reg,'')}&tlang=${localeLang}&translate_h00ked`, false);
  27. xhr.send();
  28. let defaultJson = null, localeJson = null;
  29. if (response.response && JSON.parse(response.response).events){
  30. defaultJson = JSON.parse(response.response)
  31. }
  32. localeJson = JSON.parse(xhr.response)
  33. // Merge default subs with locale language subs
  34. if (defaultJson.events.length === localeJson.events.length) {
  35. // when length of segments are the same
  36. for (let i = 0,len = defaultJson.events.length; i<len; i++) {
  37. if (defaultJson.events[i].segs[0].utf8 !== localeJson.events[i].segs[0].utf8){
  38. // not merge subs while the are the same
  39. defaultJson.events[i].segs[0].utf8 += ('\n' + localeJson.events[i].segs[0].utf8)
  40. console.log(defaultJson.events[i].segs[0].utf8)
  41. }
  42. }
  43. response.response = JSON.stringify(defaultJson)
  44. } else {
  45. // when length of segments are not the same (e.g. automatic generated english subs)
  46. let pureEvents = defaultJson.events.filter(event => event.aAppend !== 1 && event.segs)
  47. for (let i = 0,len = localeJson.events.length; i<len; i++) {
  48. let currentLocaleEvent = localeJson.events[i]
  49. let currentRawEvents = pureEvents.filter(pe => currentLocaleEvent.tStartMs <= pe.tStartMs && pe.tStartMs < currentLocaleEvent.tStartMs + currentLocaleEvent.dDurationMs)
  50. let line = '';
  51. currentRawEvents.forEach(ev => {
  52. ev.segs.forEach(seg => (line += seg.utf8));
  53. line += ' '; // add space to avoid words stick together
  54. })
  55. localeJson.events[i].segs[0].utf8 = line + '\n' + localeJson.events[i].segs[0].utf8;
  56. console.log(localeJson.events[i].segs[0].utf8)
  57. }
  58. response.response = JSON.stringify(localeJson)
  59. }
  60. }
  61. handler.resolve(response)
  62. }
  63. })
  64. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址