FlandreDaisuki / yahoo-tv-m3u8-downloader

Yahoo TV m3u8 下載
1 stars 0 forks source link

我覺得這個是有辦法做成 userscript 的 #1

Open maple3142 opened 6 years ago

maple3142 commented 6 years ago

簡單的 POC + 參考你處裡畫質的做法弄的:

// ==UserScript==
// @name         Yahoo TV m3u8
// @namespace    https://blog.maple3142.net/
// @version      0.1
// @description  Description
// @author       maple3142
// @match        https://tw.tv.yahoo.com/*
// @require      https://unpkg.com/xfetch-js@0.2.1/xfetch.min.js
// @run-at       document-start
// @grant        none
// @compatible   firefox >=52
// @compatible   chrome >=55
// ==/UserScript==

(function() {
    'use strict'
    const RES_ENUM = {
        _31: '1080p',
        _11: '1080p',
        _12: '1080p',
        _35: '540p',
        _10: '540p',
        _9: '540p',
        _36: '360p',
        _34: '360p',
        _8: '360p',
        _7: '360p',
        _6: '240p'
    }
    const open=XMLHttpRequest.prototype.open
    XMLHttpRequest.prototype.open=function(method,url,...args){
        const $=s=>document.querySelector(s)
        const u=new URL(url,document.baseURI)
        if(u.hostname.includes('yimg') && u.searchParams.get('m')==='application/vnd.apple.mpegurl'){
            const res=u.pathname.replace(/.*(_\d+)\.m3u8$/, '$1')
            const resname=(res in RES_ENUM)?RES_ENUM[res]:'unknown'
            if(resname==='unknown'){
            console.log(res)
            }
            xf.get(url).blob(URL.createObjectURL).then(u=>{
                const title=$('nav+div h1')
                const fname=`${title.textContent}-${resname}.m3u8`
                title.insertAdjacentHTML('afterend',`<a href="${u}" download="${fname}">${fname}</a><br>`)
            })
        }
        return open.call(this,method,url,...args)
    }
})()
FlandreDaisuki commented 6 years ago

你上面的我是沒辦法成功啦

不過我覺得真的要 hijack CORS request 的話 至少要把原生跟 GM_xmlhttpRequest 綁在一起用 但是這兩個的設計跟使用方法完全不一樣...

要這樣做頭有點大,我知道 ipcjs 的「解除B站区域限制」幹過很像的方法,但我後來就看不懂他的 code 了...

maple3142 commented 6 years ago

痾...為什麼要 hijack cors request...,不是直接 hook window.XMLHttpRequest 去看到底發送了哪些 request 而已嗎?

還有我剛試了一下似乎只有 firefox 不行而 chrome 可以,應該和 @run-at document-start 有關 image

Edit: 看起來是我想錯了,我剛發現下面這段 code 在 chrome 和 firefox 跑起來的效果居然不一樣... firefox 能 print 出的 hostname 居然比較少?!

const open=XMLHttpRequest.prototype.open
XMLHttpRequest.prototype.open=function(method,url,...args){
    console.log(new URL(url,document.baseURI).hostname)
    return open.call(this,method,url,...args)
}
FlandreDaisuki commented 6 years ago

也是可以啦,你是 replay 封包,我是 proxy 封包

不過我還不是很熟 Yahoo 的規則,那個底線判斷法其實很爛很不準... 我有想過去直接解碼 m2ts 找 videoHeight,但是一堆 bit operator 好麻煩zzz

maple3142 commented 6 years ago

看起來他們的 m3u8 裡面完全沒有關於解析度的資訊存在,不然就能用個 parser 去找解析度了...

FlandreDaisuki commented 6 years ago

我途中還試著用 Hls.js 來做,但還是失敗,找半天最後才找到這個奇怪的規律,只能說... 堪用 吧 需要大量實驗就是了,像我的工作細胞就不會有 _6 (240p) 還有像 _10 (1080p or 540p) 這種地雷...