分析 PPTV 视频真实播放地址全过程(Java版)
原文地址:https://www.52pojie.cn/thread-840710-1-1.html
?
分析視頻地址有什么用?
有些朋友經常會問到這個問題,其實這也是思維肌肉訓練的問題。我舉一個宋老師講過的例子(天氣預報和投資機會之間的關系)。說加勒比海出現熱帶颶風,普通小白看到這個新聞就會想和自己有什么關系呢?但是經過訓練的大腦就會上網查颶風的等級,在哪里著落,移動方位是怎么樣的。因為他知道俄克拉荷馬庫欣是美國原油期貨的交割地,颶風會造成原油淤積那里運不出去,結果是庫存增加,原油價格下跌。你還在看新聞,別人的期貨單子已經飛出去了。回到問題上來,分析的這些地址怎么用?經過訓練的人會想自己公司的 App 有哪些視頻是掛上騰訊或者其它地方的,廣告多不多,視頻質量如何。假如把視頻上傳到 PPTV 上,自己再把視頻地址分析出來,再做個播放器,那么廣告問題、視頻質量問題、帶寬問題是不是都解決了啊。有一些影音 App,基本上都是用磁鏈搜索 + 迅雷 Mini 庫來實現邊下邊播,技術痛點在哪里啊?迅雷有版權限制,大多數視頻播放不了,Seed 少播放起來也很卡。還有一影音 App 找第三方解析網站,問題是同樣的啊,線路經常被封,域名經常變化。有的朋友說:我沒上班或者我們 App 沒有播放視頻的需求。那你也可以學學里面用到的 url 簽名技術啊,將來和別的公司做數據共享的時候你們的 url 也是要加密的啊。 還有的朋友說:我根本不喜歡技術,也不打算從事程序員,這些地址對我一點用都沒有。將來你家有小孩,你可以把視頻下載到 U 盤上給孩子看啊,等等......
第三方視頻分析網站所存在問題
- 被解析的視頻網站(PPTV、騰訊)url 簽名算法改變,普遍來看,所有第三方平臺反映都很遲鈍;
- 現在各大視頻網站也在封殺這種三方平臺,服務經常被中斷,域名經常改變,需要加群得知新域名;
- 解析出來的地址依賴平臺提供的 H5 播放器,廣告一大堆,視頻清晰度還不夠。
項目運行效果
?
游客模式下,PPTV 只提供標清、高清、超清三種格式,我感覺超清的效果就能滿足觀看需求了,給出播放地址(http://v.pptv.com/show/qk3vbLiahSojradE.html),輸出標清、高清、超清,三種格式的分段視頻地址,PPTV 視頻真實的播放地址主要的獲取渠道有:智能電視、電視盒子、Web 以及 App,這次我準備分析一下如何從 Web 里找出視頻的真實播放地址。
常見的視頻播放技術的套路
現在每行都有自己的套路,比如拍電影,只要出現武裝直升機就必然會墜毀,只要出現火車那一定會出現鐵路斷裂的情形。視頻播放也不例外,常見的有 H5 播放(一般有20分鐘的限制)、P2P 播放(這個也是輔助)、ts 播放、分段播放(Flash 或 H5)等等。PPTV 就采用了分段播放+P2P輔助的方法,我們找出分段信息再反編譯出 swf 簽名算法,這樣問題就迎刃而解了。
找出播放地址
使用帶開發者模式的瀏覽器(火狐、谷歌都行)打開一個 PP 視頻,拖動進度條,然后按響應 Body 排序,你會發現播放地址:
?
?
42.56.93.26:服務器地址
16:分段視頻序號
5412864:偏移位,這個最后我們不傳
0:固定值
9fcfcdf1e6bd26c3fa64c3c7a8a73f4.mp4:視頻文件名
fpp.ver:播放器版本號
key:服務器返回的時間生成 16 位固定字符 + 16 位隨機字符,可以不傳的,這是 PPTV 迷惑我們,增加我們的破解難度
k:非常關鍵,需要解密
type:web.fpp(說明是 Web 訪問的,App 這個值是不同的)
vvid:播放唯一標識,統計廣告展示次數,檢測卡頓時用的,我們同樣不傳
上面的地址是誰發出請求的呢?
?
原來是一個叫做“player4player2.swf”的文件發出的,可以斷定這就是播放器文件,我們現在要反編譯它,先把這個 swf 下載到本地磁盤,然后用 AS3 Sorcere 打開這個文件(反編譯),最好是把反編譯的源代碼導出來,然后用 Sublime Text 打開比較好(可以全局搜索)。
計算 k 值
我們搜索 "k": 找到賦值的地方,當 flag 和 iv 不為空的時候就用 Decrypt 計算 k 值:
?
再搜索 Global.getInstance()["crypto"],找到定義它的地方:
?
上面的 new this.Crypto() 引用的是 VodFacade_Crypto 類,找到 VodFacade_Crypto 類發現是空類,原來是 PPTV??把核心算法以 swf 的方式嵌入到類里面了,我們要把 VodFacade_Crypto 這個空類的內容提取出來。用 Flash Builder 新建一個 Flex 項目,代碼如下:
[Actionscript3]?純文本查看?復制代碼
?
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" ??????xmlns:s="library://ns.adobe.com/flex/spark" ??????xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" ??????applicationComplete="init()"> ?<fx:Declarations> ??<!-- 將非可視元素(例如服務、值對象)放在此處 --> ?</fx:Declarations> ?<fx:Script> ??<![CDATA[ ???import flash.display.Loader; ???import flash.events.Event; ???import flash.net.URLRequest; ???import mx.core.ByteArrayAsset; ???private var byteArray:ByteArrayAsset; ???? ???private function init():void{ ????var _loader:Loader = new Loader(); ????_loader.load(new URLRequest("player4player2.swf")); ????_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfComplete); ????function swfComplete(event:Event):void ????{ ?????var myClass:Class = _loader.contentLoaderInfo.applicationDomain.getDefinition("VodFacade_Crypto") as Class; ?????byteArray = new myClass as ByteArrayAsset; ????} ???} ???? ???private function onSaveClick():void ???{ ????var fr:FileReference = new FileReference(); ????fr.save(byteArray, "VodFacade_Crypto.swf"); ???} ??]]> ?</fx:Script> ?? ?<mx:Button label="Save File" left="10" top="10" id="saveButton" click="onSaveClick()" /> ? </s:Application> |
這里要注意,把 player4player2.swf 放到 bin-debug 目錄中,運行后點擊 Save File 按鈕,彈出另存對話框保存為 swf 文件,我們在用 AS3 Sorcere 打開這個保存的 swf 文件就看到計算 k 值的方法了。
計算 key 值(和上面的 k 不是同一個)
通過上圖不難發現 key 值的計算是用 constructKey 方法生成的,同樣搜索 constructKey:
?
有了 as3 源碼改成 Java 代碼就不難了,這里要注意原版 as3 的位運算是用無符號整型,Java 沒有這個類型,只能用 Long 模擬。
找出視頻分段信息請求地址
到現在為止,我們已經分析出 k 值、key 值,現在要做的是怎么找出視頻分段信息。還是用之前的方法,找一找哪些文件是由 player4player2.swf 發出的:
?
果真找來了,原來是個 xml 文件,我們來分析一下:
這個串參數比較多,實際上我們根本用不到,先看這個“webplay3-0-29412562.xml”,其中“webplay3-0-”是固定值,我們不關注,29412562.xml 里面的數字我們可以在播放網頁的源代碼找出來。
appplt、appid、appver、type,我們需要這四個值,具體為啥別的值不要下面再說。
param 參數有4個值非常關鍵,少了任何一個就被判定為盜鏈。
ahl_ver:固定值(默認值為1)
type:固定值(默認值為web.fpp)
ahl_random:16 位隨機字符
ahl_signa:ahl_random + "web.fpp" + "-" + "1" + "V8oo0Or1f047NaiMTxK123LMFuINTNeI" 用這幾個值拼串然后用 SHA256 編下碼
把這幾個參數拼起來加上地址訪問后就可以得到視頻分段請求地址了。
現在驗證一下我上面說的算法,搜索 ahl_random 找到如下方法:
?
看到沒,這里面還有 VIP 相關的參數等著你發掘新的功能。
回頭看
還記得我們計算 k 值的時候所有到的 flag、iv 的值在哪里嗎?我們看看上面這個 xml 的內容:
?
channel 節點
- nm -- 視頻標題
- pic??-- 視頻縮略圖
dt 節點
- rid -- mp4文件名
- sh -- 服務器地址
- st??-- 請求時間(以請求時間為準,計算過期時間)
- id??-- 視頻主鍵
- bh -- 備份服務器地址
- flag -- 這個沒猜出來
- iv? ?-- 這個也沒猜出來
- key -- 需要解密
dragdata 節點
- sgm -- 視頻播放地址序列
dt 節點里有我們計算 k 值所需要的參數,如果你打算自己開發播放器(帶播放進度條功能),那 sgm 里的?dur(時長)、fs(大小)、os(偏移量),就很重要了。
至此,PPTV 視頻的真實播放地址在技術層面已經徹底脫光了給我們看,實際上算法非常簡單,我稍后把 Java 源代碼發到 github 上給大家下載,謝謝觀看。
開源地址
https://github.com/qiuqiu3/pptv
把項目下載后導入到 MyEclipse 中,右鍵 App.java 那個類-》Run as -》Java Application。
總結
以上是生活随笔為你收集整理的分析 PPTV 视频真实播放地址全过程(Java版)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DLP和3LCD投影仪技术有什么区别?怎
- 下一篇: C++: STL: atomic