訓練家的佈弱格-Patch1.2

The BLOG of trainer



編輯日期:2022-09-24 23:31

類型:電腦應用
作者:羽山
文章時間:2022-09-24 23:31:11
瀏覽人數:811人
標題:Netflix 雙字幕開發心得
網址:https://3wa.tw/blog/blog.php?id=1986
內容:
 

 

 

花了不少時間,總算把 Netflix 雙字幕作出來了~~~(撒花)

 

使用方式與之前 3waNetflix V1.8 以前都相同,啟動後

我把原本官方的字幕畫面,複製一份放到分頁 tab 裡的「字幕選擇」空間

 

 

在字幕選擇可以切換音訊、主要字幕、次要字幕

 

 

主要字幕就與之前的設定方式一樣

 

 

第二行的字幕通常大家會用英文吧,所以預設的字體大小跟字距稍微調小調宅些

 

V1.9 算是滿大的更新,作起來相當累人...

(2022-09-24) V1.9 版:

  1、加回 jQuery 3.6.0

  2、雙字幕功能

  3、第二字幕 UI 設定介面

  4、加入字型選擇

  5、使用者正在「準備切換下一集」或「選集數」 或 「調影片速度」,停用設定 UI

  6、UI 控制區,只有滑鼠進入的高度 70% 切入才有效,不然螢幕太小時,調時間軸也會一直檔到

  7、原 3wanetflix 的字幕要插在 video 裡,這樣全螢幕才有作用,現在發現要再 video 外層的 div 才行

  8、修正字幕不需要強制大寫:font-variant: small-caps

  9、主要字幕、次要字幕可各自設定樣式

  10、如果有下一集、工作人員名單、返回瀏覽、略過簡介,要可以點

  11、已知問題:

(1). 啟動 3waNetflix V1.9 版後,下方進度條會失蹤,需要用滑鼠滑過下排音量控制才會出現

(2). 當滑鼠進入下排控制區時,字幕功能就會暫停,請往上移開

(3). 已知有些改 1080p 或是部分字幕是「圖片型字幕」出字會異常,之後再研究

 

然後來寫點開發過程的心痠:

禮拜一主管 Jeffrey 聽說我有在作 Netflix Plugin 可以放大、改字幕顏色的功能,問說能不能加個

雙字幕,這樣方便學英文還是其他語言。自己也是很期待這個功能開發能不能實現~~

初期開發在看 Netflix 一直按 F12 ,從 console 裡面找看看有哪些資料能用,但一直都找不到

與 track、語言有關的資訊,localstorage 也沒有

 嘗試在 window 找了許久,沒找到有用的資訊可以幫助雙字幕

 

然後羽山想嘗試找出網頁裡會呼叫字幕連結的位置,比如點了「英語字幕」會抓到一個 xml 的位置

 

然後利用 source 攔截,一步一步看,就一直進入 window.a000 的虛空

看不太出來他加密後的邏輯怎麼解算

羽山之前有找到一篇網友提供 Request 加載的 xhr ,是直接改寫 ajax 呼叫方式:

From : https://stackoverflow.com/questions/25335648/how-to-intercept-all-ajax-requests-made-by-different-js-libraries

 

(function(open) {

    XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {

        console.log(url)

        this.addEventListener("readystatechange", function() {

            console.log(this.readyState); // this one I changed

        }, false);

        open.call(this, method, url, async, user, pass);

    };

})(XMLHttpRequest.prototype.open);

如此一來,任何 ajax 呼叫後,都可以從中提取曾呼叫的 url 網址~~~

或是重新註冊 JSON.parse ,把 global JSON.parse 改寫成一樣會作 json decode 但可以把值寫到自己想要的變數,測錄 json 包。

這二個作法可能在 chrome extension V2 比較有機會達成,自從升 V3 以後,直接變成 background service_worker,初期光 access html dom 就有點中混亂,得讓使用者自己 chrome.action.onClicked

這個作法是參考另一個 NflxMultiSubs 開源專案裡的一段 code

// Hook JSON.parse() and attempt to intercept the manifest
// For cadmium-playercore-6.0022.710.042.js and later
const hookJsonParseAndAddCallback = function(_window) {
  const _parse = JSON.parse;
  _window.JSON.parse = (...args) => {
      const result = _parse.call(JSON, ...args);
      if (result && result.result && result.result.movieId) {
          const movieId = result.result.movieId
          console.log(`Intercepted manifest ${movieId}`);
          window.__NflxMultiSubs.updateManifest(result.result);
      }
      return result;
  };
};
hookJsonParseAndAddCallback(window);

寫的真的很猛~~學習到這個技術真是痛快啊XD,以前怎麼都沒想這麼作...

如果 V3 可以用就好了 :( 權限不知道要怎麼加才辦的到...
熬夜試了一、二個晚上沒成功,就繼續照自己原來的土炮繼續作 XD

一個大膽的想法,就是如果一直按「繁體中文、英文」,反覆一直按呢...
沒錯,按完後可以拿到「繁中、英文」而且只有第一次他會xhr載字幕,稍微頓一下
之後切換都相當順暢


從這個角度切入後,要克服的就是不能讓「選字幕的位置不見」,Netflix 有個奇怪的設計
他不需要的東西,直接從畫面 remove 掉,不是隱藏呦,直接 remove...

比如你在選「某一集」的選單開啟,這時他的「時間軸」看似隱藏,實際也是 remove 掉
整個 dom 元件不給你操作,笑死...

所以土炮仔羽山的作法,就是讓一個屁孩,一直狂點右下角的字幕,只要一直點就不會消失...
然後再一直反覆點你要的字幕(繁中、英文),點完再收集到記憶體位置,然後再用自己的字體樣式
重新拚裝後,插到網頁裡的畫面


測試的範例程式:


這段程式是我最初測雙字幕寫的

前面那堆 js 就 jQuery-3.6.0.min.js

流程:
1、載入 jQuery
2、隱藏原本的字幕(因為要用雙字幕合併後的字幕)
3、隱藏右下角字幕選單(註解掉,沒執行,這樣大家比較明白)
4、跑一個 Interval ,裡面再跑三組 timeout
  (1) 一直按右下角那個「字幕」的按鈕,讓選單出現
  (2) 按「繁體中文」,等100ms
  (3) 取得繁體中文字的內容,再按「英文」,再等100ms
  (4) 將「取得的中、英文」合併成一組文字,如果這組跟之前一樣,就不顯示了
  (5) 在 body 插一個浮動 div[reqc='myword'] ,然後把字的樣式設一設就顯示

(話說 Netflix 的工程師好像很愛用 屬性 data-uia,而羽山自己很愛用 reqc)
查了一下才知道這個也有 w3c 規範:https://www.w3schools.com/tags/att_data-.asp



這個測試看來是有成功了~那麼可以土炮達成就成功了一半~~~(大心~撒花)

接下來就偷工簡料,重新引入 jquery ,之前自己寫 jquery-light 還是沒辦法把事件寫的那麼完美
重新把肥肥的 jquery-3.6.0.min.js 塞入程式的最開始,因為不知道怎麼用 js 檔引入,所以就放
在程式碼的最前面...(笑)

 塞入整包的 jquery 真的事半工備...

可惜短命的 jquery-light (By 3wa FeatherMountain...),換成正牌 jquery 幾乎沒改啥 Code 就直上,當初努力想實作還是很有價值~

短命的 jquery-light 也是從 v0.5~v1.8 很努力工作了

接下來講到哪了~

對了~講到拷貝字幕 UI

 拷貝後的字幕 UI 可以省下很多自己刻的時間

但拷貝完後的字幕選單,要確保這是單向使用,原來的官方選單就隱藏放到 z-index:-2 藏起來

然後在點擊時,先把「勾勾」的SVG 樣式、點到的亮字、暗字 class 都記下來,當使用者在點擊時

就註冊新的勾勾,註冊亮、暗字,然後把使用者點擊「主要字幕、次要字幕」寫到 localstorage、global window 裡。

這裡羽山用 my_netflix_sub1、my_netflix_sub2

神奇的點雙字幕小人就會一直幫你點這二個字幕,點個不停。

有些情況是不能點的,剛才提到如果使用者想使用時間軸、換下一集、選集、全螢幕、調整影片速度…

當滑鼠觸及這些東西,就不能讓小人再點擊字幕按鈕、字幕選擇

 如程式碼 1295 行附近,就是在指這個情境

當一切都很美好時,發現全螢幕一點下去,又變成地獄了…

所以改寫 netflix 的全螢幕按鈕

新的全螢幕寫法參考:https://usefulangle.com/post/12/javascript-going-fullscreen-is-rare

這寫的還真是符合我需要的功能,直接把這段拿來用,然後全螢幕整個 body 就接近90%成就達成^_^~

 

目前美中不足就是因為小人一直在點字幕,所以 timeline 時間軸會很不好按

於是把整個下排控制 bar 作了一個 body onmousemove 的區塊,滑鼠一進去,小人就不點了

此時滑鼠只要經過原本下排任意一個功能,時間軸就會顯示出來

也因為小人不幫你點,所以滑鼠在下排控制區,就多了一行文字提示...

 滑鼠在下方控制區時,雙字幕將無法正常使用

因為小人沒在點了齁

 

總之還有一個大魔王要克服,就是像「2077 電馭叛客:邊緣行者」裡的「日文字幕」

他是使用「圖片型」的字幕~在舊的 V1.8 我有實作可以調整大小、高度,但樣式都無法調整

在這個版本我目前爆肝有點嚴重,最近都二、三點才睡,所以完全沒修他...

 

選了圖片型的日文字幕,目前就會變成這樣

或是使用者安裝了嘻花的 1080p extension 

 

老實說我不知道那個 1080p 到底畫質有沒有比較好,但載入後都是抓圖片型的字幕,相當奇妙

以上大概就是我目前 V1.9 Beta 的一些心得

 

2022-09-26 補充:

昨晚在奮戰圖片型的字幕,$("svg image") 的 href,值如:

blob:http://www.netflix.com/..........................................

這個用法經過一連串查找相關的資料,最接近的使用方法是:

URL.createObjectURL(blob); 

但 blob:URL 這種 data urls 是上面那行執行完的成果

且他在畫入 image 元件後,應該馬上就又執行 URL.RevokeObjectURL 把顯示後的結果回收

土炮的字幕來回切換的過程,就無法延續使用 blob 的內容,就算用 jquery clone obj 也

無法正確的把 svg image 複製出來在另建的空間裡呈現

思來想去到凌晨四點還睡不著:( 早上八點多忽然驚醒,眼看要遲到,不如就請特休一小時休息好好準備上班,就在請完假後,腦中忽然出現一個想法~~

「background service 到底能不能 inject 啊…就算他有嚴格的 meta Content-Security-Policy」

但是否就作到滴水不漏!?

這個想法迫使我再一次挑戰 inject script

想法很簡單,利用 <img onerror=""> 注入 script 看看呢!?

然後要注到他的 window 也能覆蓋齁~如果注的下去,那 extension V2 的寫法,就可以整個搬來 V3 了

所以先假設...

<img onerror="alert('test');" src="//3wa.tw/xxxx">

隨便加載一張失敗的圖,載入後,居然有跳出 alert 呢~~~

那麼...

<img onerror="URL.createObjectURL = null;"> 看看會不會整個日文字幕都壞掉?

咦,失敗了

那麼

<img onerror="window.URL.createObjectURL = null;"> 呢!?

靠B,成功了~~~笑死

原來還可以這樣硬幹一張假圖,onerror 去把整個網站的 js 注成我插的啊....囧>

這樣就有趣了,我只要再註冊一次他的 URL.createObjectURL、JSON.parse 就什麼事都能作了啊

之前這麼土炮還真辛苦 XD

所以你各位裝來路不明的 extension 最好看仔細他們寫了什麼鬼東西啊...

為了讓「流過的圖片blob」可以被攔劫,所以我作了一點點擴充,我把 blob 的內容用

FileReader 開啟,然後在 body 放一個可以藏 base64 的 div 作為資料交換空間

 

var reader = new FileReader();  // 加載 FileReader

reader.onload = function() {

var dom = document.querySelectorAll("div[reqc='my_netflix_imageSubsB64']");

if(dom.length==0) return;

  var dataUrl = reader.result;

  var b64 = dataUrl;

  var m = dom[0].innerHTML.split('|||3WA_BR|||');

  //字幕|||3WA|||時間

   m.push(b64+"|||3WA|||"+new Date().getTime());

  m = m.slice(-10); /* keep last 10 */

  dom[0].innerHTML = m.join('|||3WA_BR|||');

 };

 

這個 div html 的內容會保留最後抓到的十張字幕影像

內容為

base64|||3WA|||當時的時間

|||3WA_BR|||   --> 這是斷行

base64|||3WA|||當時的時間

|||3WA_BR|||   --> 這是斷行

 

大概是這樣,出字幕的時候,大概只需要針對還持續更新的字幕(大概0.5秒內吧,最多二組不同內容的字幕)

這樣應該就可以把圖片的字幕作出來,擺在我想放的空間裡

 

日文的圖片字幕常常滿多特別效果,之後再考慮如果屬特殊位置的字,再作調整

 

 

 總算作出 V2.0 版了,這次 UI 調整後較為緊緻一些

然後原來滑鼠移入中間就會出現,改成要點選右下原來的字幕按鈕

 

由於重新定義了 URL.createObjectURL 昨晚測下來,發現如果回 Netflix 首頁,再重新點回影片播放頁

都會出現 Netflix 錯誤異常,需要重整瀏覽器,把新加的定義註解掉後,就不會當機

所以在 appClass.method 加入 fixOrinURL:

狀況一:

如果畫面不是播放頁時,且發現 URL.createObjectURL 有改寫,就還原原版

狀況二:

如果使用者按「下一集、切換其他集」這裡畫面仍是播放頁,但仍會當機,解決方法就是把這二個按鈕,再 bind click,按下去就還原原版

經過這一波操作就不會 netflix crash

 

V2.0 作了以下修正調整:

  (2022-09-27) V2.0 版:

  1、使用注意事項獨立一個 tab 分頁

  2、圖片型字幕閃耀問題修正

  3、當畫面靜置一段時間,會發生無法回上頁、右上的問題反應也無法點選

  4、調整 UI 時,有時會失效

  5、無人說話時,字幕退場的時間不精準  

  6、如果使用者在調整時間軸,延長消失時間(6秒)

  7、全螢幕時,滑鼠沒移動一段時間後要自動隱藏(6秒)

  8、縮小設定畫面可以觸發顯示的範圍

  9、調整畫面很容易滑鼠移動就消失,將 mouseout 改成 mouseleave 後較為正常

  10、UI 控制區,只有滑鼠進入的高度 36% 切入才有效,不然螢幕太小時,調時間軸也會一直檔到

  11、UI 控制區,改成點右下角語言,並加入嘻花效果

  12、英文字幕,二行字會黏在一起

  13、UI 控制區畫面改緊緻,滑塊加大

  14、播放結束後,按下一集異常

  15、直接按下一集的三角按鈕

 

 

 

 

 (V2.0 畫面) 字幕語言選單

 

 

(V2.0 畫面) 主要字幕

 

 

(V2.0 畫面) 次要字幕

 

 

(V2.0 畫面) 注意事項獨立收在一起

 

 

 

 有興趣一起研究的同好也歡迎加入

 

 

真是美好的一天,能作出來真的很開心~~~

2022-09-27 09:41 羽山筆

 

 

 

 

 

 


 

 

 

 

 

 

 

 

首頁  上十頁  上一頁  1 下一頁    最末頁 (總共有...1頁)

第 1 頁

有話要說  看留言 【2】

其他分類
當月訓練
(2022-09-24)
【電腦應用】Netflix 雙字幕開發心得

(2022-09-23)
【NSR 150】NSR150 被拍照檢舉到環保檢驗站驗車心得

(2022-09-21)
【遊戲 / 生活】腳踏車車燈維修 Fuuga

(2022-09-22)
【遊戲 / 生活】小米充電寶維修 20000mha

(2022-09-09)
【酷龍 150】NK酷龍 150 汽油幫浦故障

最新訓練
(2022-11-26)
【遊戲 / 生活】開箱 MIBOXER CA-12A 充電器

(2022-11-24)
【機車綜合相關】製作墊片打孔機特工

(2022-11-20)
【NSR 150】NSR150 左曲軸箱電盤側組立

(2022-11-19)
【NSR 150】NSR150 右曲軸箱離合器側組立

(2022-11-13)
【遊戲 / 生活】製作簡易電池測試平台

(2022-11-13)
【遊戲 / 生活】製作萬力快拆木板夾

(2022-11-13)
【焊接】萬能鉗維修

(2022-11-11)
【機車綜合相關】簡易含氧感知器測試機-Part3

(2022-11-06)
【NSR 150】NSR150 曲軸箱組立

(2022-10-30)
【NSR 150】NSR150 曲軸軸承、曲軸安裝