使用uniapp打造Android TV,实现自己专属电视机App

7,865 阅读7分钟

一.原理简述

拿到腾讯视频的播放地址,和各大视频解析网址进行拼接成新的地址。然后通过Puppeteer库控制chrome打开拼接的地址监听当前网站的请求,通过正则匹配MP4和m3u8拿到真实的播放地址,当然我这种方法是比较笨拙和效率低下的。还有的方法是可以逐个研究破解视频解析网站,直接通过网站的接口进行获取真是播放地址,但是目前大部分网站都是各种无限debugger阻止你进行源码研究和各种iframe嵌套阻止你爬虫获取播放地址。我这边只破解2个视频解析网站,后面有机会再分享给大家。

二.安卓TV的开发

1.创建uniapp工程

  • Android TV开发我采用了uniapp打包成android App,对的打包成andriod应用就可以在电视机上使用了。
  • uniapp创建项目有2中方式
    • 1.通过HbuilderX工具直接创建
    • 2.通过cli脚手架打架
  • 两种方法都可以,我这边是直接通过HbuilderX的创建,具体创建步骤可以直接去官网查看教程 HbuilderX官网uniapp官网,这里不在详叙。

2.引入Uniapp-TV组件

  • 我这里主要使用了码云上一个小伙伴贡献的## [Uniapp-TV]组件库(gitee.com/javaleon/un… "Uniapp-TV"),此组件库实现TV遥控器焦点控制功能,使我们的App能通过遥控器进行简单的交互。

  • 组件的安装

    git clone https://gitee.com/javaleon/uniapp-tv.git
    
    • 将项目克隆到本地

    • 然后将compoents文件下的组件复制到你的项目compoents目录下,并将store复制到你的项目根目录下;

image.png

  • 组件的使用

    • 在page.json设置一个自动引入,就不需要每个页面申明式的引入组件了
      "easycom" : {
        "autoscan" : true,
        "custom" : {
            "unitv-(.*)" : "@/components/unitv-$1/unitv-$1.vue"
        }
      },
    
    • Uniapp-TV组件库主要有6个组件:

      • unitv-page 代表一页,所有焦点控制内容都需要在它内部
      • unitv-zone 代表一块区域,相当于将所有焦点进行分组,方便控制区域之间切换
      • unitv-item 代表一块区域内的一个子项
      • unitv-scroll代表一块区域内子项超过屏幕宽度 当下一焦点不可见时,需要滚动至可见范围
      • unitv-video 封装video组件并用于监听按键控制暂停,播放,快进,快退
    • 页面返回时需恢复当前页显示,可在onShow生命周期中调用unitv-page的showPage方法。unitvPage为unitv-page组件的ref的值 if (this.refs.unitvPage) { this.refs.unitvPage.showPage() }

    • 具体的使用方法可以查看[Uniapp-TV组件库文档](gitee.com/javaleon/un…

3.关于调试

  • 我这边是直接使用的Andriod studies下载的Android Tv模拟器

image.png

4.关于配置

  • 修改uniapp的默认尺寸基准,因为我们是大屏幕的所以不能按照750的基准来了,直接在pages.json的globalStyle配置项添加一下内容:
"globalStyle": {
		"navigationStyle": "custom",//去掉导航栏
		// 重点
		"rpxCalcMaxDeviceWidth": 2560, // rpx 计算所支持的最大设备宽度,单位 px,默认值为 960
		"rpxCalcBaseDeviceWidth": 1920, // rpx 计算使用的基准设备宽度,设备实际宽度超出 rpx 计算所支持的最大设备宽度时将按基准宽度计算,单位 px,默认值为 375
		"rpxCalcIncludeWidth": 2560 // rpx 计算特殊处理的值,始终按实际的设备宽度计算,单位 rpx,默认值为 750
	},

三.后端开发

1.用到的技术简介

  • 使用koa2搭建的后端服务,使用koa2-cors解决跨域问题,koa-router做路由,axios进行http请求;
  • 关于puppeteer包
    • 它是一个nodeJs的包,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。
    • 通过它我们就可以控制个浏览器打开并输入网址可以拿到网页里面的内容。

2.puppeteer的使用

  • 详情的使用文档请查看puppeteer中文文档
  • 因为调用腾讯接口的时候需要用到cookies不然返回的列表数据不准确,所以下面的代码是为了获取腾讯视频的cookies,并将cookies缓存到全局的global中方便调用。
const puppeteer = require("puppeteer");
exports.getCookies = async () => {
  const browser = await puppeteer.launch();//打开一个浏览器
  const page = await browser.newPage();//打开一个tab
  await page.goto("https://v.qq.com/x/cover/mzc002007knmh3g/y00455moxwy.html", {
    waitUntil: "networkidle2",
  });//打开一个网址
  let cookie = await page.cookies();
  let cookieObj = {};
  let cookieStr = "";
  cookie.forEach((element) => {
    cookieObj[element.name] = element.value;
    cookieStr += element.name + "=" + element.value + "; ";
  });
  await page.close();
  global.cookie = cookieObj;
  global.cookieStr = cookieStr;
  await browser.close();
};

3.获取腾讯视频的列表数据

image.png

  • 打开浏览器的开发者调试工具,输入腾讯视频网址就通过netword就可以查看接口地址和参数 https://pbaccess.video.qq.com/trpc.vector_layout.page_view.PageService/getPage?video_appid=3000010这个就是获取列表的接口,下面是请求的参数
{
    "page_context": null,//第一页可以传空,下一页的请求参数在上一页请求的数据中可以拿到
    "page_params": { 
        "page_id": "100101", //分类id,如精选、电视剧、电影,均可从腾讯视频播放页的window.__pinia中获取
        "page_type": "channel" //这个可以默认写死
      },
    "page_bypass_params": {
        "params": {
            "caller_id": "3000010",//默认即可
            "data_mode": "default",//默认即可
            "page_id": "100101",
            "page_type": "channel",
            "platform_id": "2",//默认即可
            "user_mode": "default"//默认即可
        },
        "scene": "channel",
        "abtest_bypass_id": "969f0554a0743a45"//从cookies中获取,即cookies中的video_guid字段
    }
}

  • 通过上述方法可以获取影片详情和剧集还有筛选影片等,这里我就不一一介绍了。

  • 通过axios发送请求获取返回的数据对数据进行加工处理直接返回给前端即可,记得把cookies带上去

 headers: {
        "access-control-allow-credentials": true,
        cookie: global.cookieStr,
      },
  • 从返回的列表数据中拿到cid和vid通过拼接就可拿到腾讯视频的播放地址 let txUrl=https://v.qq.com/x/cover/${cid}/${vid}.html

  • puppeteer的使用监听视频解析网站请求拿到真实播放地址
    视频解析网址:https://jx.aidouer.net/?url=

const browser = await puppeteer.launch();
const page = await browser.newPage();
let url=“https://jx.aidouer.net/?url=” +"txUrl"//txUrl为上面腾讯的播放地址
page.goto(url, { waitUntil: "networkidle2" });//打开视频解析网址
let playUrl = await new Promise((resolve) => {
    //监听网站的请求
    page.on("request", (response) => {
    let url = response.url();
    let regx = /\.(mp4|m3u8)/;
    //匹配到mp4和m3u8后缀的网址返回给前端
    if (regx.test(url)) {
          resolve(url);
        }
      });
     setTimeout(function () {
       resolve(false);
     }, 10000);
    });
    page.close();
    browser.close();
  • 这边贴一下其他的视频解析网址地址,以下地址没有经过全部测试,仅供参数使用
let playLine = [
    { name: '爱豆', url: 'https://jx.aidouer.net/?url=', mobile: 1 },
    { name: '纯净1', url: 'https://z1.m1907.cn/?jx=', mobile: 1 },
    { name: 'B站1', url: 'https://jx.bozrc.com:4433/player/?url=', mobile: 1 },
    { name: 'BL', url: 'https://vip.bljiex.com/?v=', mobile: 0 },
    { name: '冰豆', url: 'https://api.qianqi.net/vip/?url=', mobile: 0 },
    { name: '百域', url: 'https://jx.618g.com/?url=', mobile: 0 },
    { name: 'CK', url: 'https://www.ckplayer.vip/jiexi/?url=', mobile: 0 },
    { name: 'CHok', url: 'https://www.gai4.com/?url=', mobile: 1 },
    { name: 'ckmov', url: 'https://www.ckmov.vip/api.php?url=' },
    { name: 'H8', url: 'https://www.h8jx.com/jiexi.php?url=', mobile: 0 },
    { name: 'JY', url: 'https://jx.playerjy.com/?url=', mobile: 0 },
    { name: '解析', url: 'https://ckmov.ccyjjd.com/ckmov/?url=', mobile: 0 },
    { name: '解析la', url: 'https://api.jiexi.la/?url=', mobile: 0 },
    { name: '老板', url: 'https://vip.laobandq.com/jiexi.php?url=', mobile: 0 },
    {
        name: '乐多',
        url: 'https://api.leduotv.com/wp-api/ifr.php?isDp=1&vid=',
        mobile: 1,
    },
    { name: 'MAO', url: 'https://www.mtosz.com/m3u8.php?url=', mobile: 0 },
    { name: 'M3U8', url: 'https://jx.m3u8.tv/jiexi/?url=', mobile: 0 },
    { name: '诺讯', url: 'https://www.nxflv.com/?url=', mobile: 0 },
    { name: 'OK', url: 'https://okjx.cc/?url=', mobile: 1 },
    { name: 'PM', url: 'https://www.playm3u8.cn/jiexi.php?url=', mobile: 0 },
    {
        name: '盘古',
        url: 'https://www.pangujiexi.cc/jiexi.php?url=',
        mobile: 0,
    },
    { name: '全民', url: 'https://jx.blbo.cc:4433/?url=', mobile: 0 },
    { name: '七哥', url: 'https://jx.mmkv.cn/tv.php?url=', mobile: 0 },
    { name: 'RDHK', url: 'https://jx.rdhk.net/?v=', mobile: 1 },
    { name: '人人迷', url: 'https://jx.blbo.cc:4433/?url=', mobile: 1 },
    { name: '思云', url: 'https://jx.ap2p.cn/?url=', mobile: 0 },
    { name: '思古3', url: 'https://jsap.attakids.com/?url=', mobile: 1 },
    { name: '听乐', url: 'https://jx.dj6u.com/?url=', mobile: 1 },
    { name: '维多', url: 'https://jx.ivito.cn/?url=', mobile: 0 },
    { name: '虾米', url: 'https://jx.xmflv.com/?url=', mobile: 0 },
    { name: '云端', url: 'https://sb.5gseo.net/?url=', mobile: 0 },
    { name: '云析', url: 'https://jx.yparse.com/index.php?url=', mobile: 0 },
    { name: '0523', url: 'https://go.yh0523.cn/y.cy?url=', mobile: 0 },
    { name: '17云', url: 'https://www.1717yun.com/jx/ty.php?url=', mobile: 0 },
    { name: '180', url: 'https://jx.000180.top/jx/?url=', mobile: 0 },
    { name: '4K', url: 'https://jx.4kdv.com/?url=', mobile: 1 },
    { name: '8090', url: 'https://www.8090g.cn/?url=', mobile: 0 },
]

四.打包app,部署后端服务

  • 将uniapp打包成app,通过u盘安装到电视机上

  • 部署后端服务。

  • 最后后放上我的200块买的投影仪安装app后的效果,200买的机子太垃圾操作起来很卡很卡有时候全屏播放会闪退,但是放在我家小米电视上没有以上问题。

  • 第一次写文章,写的不好请大家见谅哈!有问题可以留言,我知道的我一定会回答的哈~

    • 【免责申请】本文档仅用用于交流学习,请勿用于商业!

image.png