Skip to content
Projects

Yu2002s/DongYuTVWeb has 303 GitHub stars and 35 forks. GitHot measured -1 in 7 days. Last checked 2026-11-10 21:13 UTC. Last push 2026-08-20.

How these counts are measured

这是一个电视浏览器项目,可以在电视上观看直播。

Measured star growth

in 24h
Update delayed
in 7 days
-1
in 15 days
Collecting history
in 1 month
Collecting history

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

README.md

Original

DongYuTVWeb

轻松在电视上观看直播,操作简单,适合家中老人使用,使用 WebView JavaScript 注入方式实现

交流/反馈

  • QQ 群

交流/反馈QQ群

  • 公众号

公众号

  • App发布网站

App发布中心

  • 相关问题解答

相关问题解答

下载

应该如何下载呢?

App发布中心

  1. 请在 release 下载。
  2. 如果你用的是手机,一般内核版本高,可以在 release 下载体积最小的,电视则下载体积大的。
  3. 一般android版本高的话,下载体积最小的就行,实在不行都可以下载试试。
  4. 市面上一般设备是64位的,请下载文件以app_arm64开头的文件, 老设备下载 app_arm32 开头的。

操作

  • 方向上: 上一个频道
  • 方向下: 下一个频道
  • 左键: 声音减
  • 右键: 声音加
  • 确定键: 换台
  • 数字键: 换台
  • 菜单键:设置
  • 连续按两下菜单键:换源
  • 返回键:返回/退出
  • #号键:强制刷新当前频道(有问题时使用)

使用老式的闭路电视操作,适合老人使用!

安装

远程安装

目前 1.0.13以上版本支持远程安装,需要用户在手机端,打开 设置 -> 远程安装 -> 通过 ip 和 端口连接到电视,点击远程安装即可 如何连接呢?tcl电视举例(其他品牌电视请问AI或百度):需要电视开启adb,进入 设置 -> 关于 -> 依次按下 上下左右 ,之后会显示扩展设置, 找到开启adb开关。然后打开设备的网络信息(WIFI详情),查看 IP V4地址,这个就是 ip,一般默认的端口填写 5555 即可

此方法也能用来更新,如果你不会使用,请使用下面方法安装和更新

其他方式

  1. USB数据线连接电视和手机(或U盘),打开手机的通知,将仅充电改为文件传输,然后把安装包复制到电视,电视找到相关USB存储,安装apk
  2. 通过无线方式安装,需要 android 11 以上,打开电视 adb调试(如何开启请百度),使用甲壳虫adb助手连接电视后安装

具体请百度或问AI,这里不进行详细描述

安装事项

有些电视限制安装第三方App,需要使用 adb 禁用软件包安装程序

tcl电视举例(其他品牌电视请问AI或百度):需要电视开启adb,进入 设置 -> 关于 -> 依次按下 上下左右 ,之后会显示扩展设置, 找到开启adb开关,然后使用 https://www.jiakechong.net/ 甲壳虫adb助手 连接到电视, 连接之前需要获取电视在网络中的ip,打开电视网络信息会有ipv4 地址,这个就是。然后用甲壳虫找到应用管理, 禁用软件安装包程序就可以安装app了。 安装完成之后再把软件安装包程序启用。

开机自启动

远程设置开机自启

  1. 在手机端打开本App的 设置 -> 远程连接 -> 连接电视。
  2. 点击操作按钮 -> 开启自启动 -> 设置默认桌面

手动设置

  1. 查找电视的一些设置、App,看看有没有应用自启动相关的设置,对本应用开启自启动。可百度或 Ai 搜索自启动相关文章
  2. 确保 App 已经打开过,并允许了悬浮窗权限
  3. 设置默认的桌面,一般按 Home键(主页键) 会提示设置默认桌面,可以设置为本App并选择始终,或查找电视相关设置和App设置默认桌面

不保证所有电视都支持,仅在原生系统虚拟机 Android 12 测试通过

如果上面的方法不奏效,可以尝试以下方法:

  1. 进入电视的工厂模式
  2. 开启 USB 调试
  3. 使用无线调试或数据线连接电视和电脑(手机-需要安装终端)电脑安装adb 手机可以安装MT管理器,自带终端
  4. 进入终端,输入以下命令
# 无线连接 adb connect ip:端口
adb devices # 查看设备是否连接成功
adb shell # 进入管理员模式
cmd package set-home-activity "xyz.jdynb.tv/.MainActivity" # 设置默认的启动项
reboot # 重启设备

注意:定制系统可能无效

无法播放问题

软件已内置X5内核,如果你设备安装失败会有问题请反馈!具体看【下载】

部分设备仍然无法正常使用,这时候需要手动下载并安装 AndroidSystemWebView (需要梯子)

这里提供以下下载地址:

自定义频道

目前不支持自定义源,如果你需要添加自己的源,请在公众号给我私信

频道完整配置文件 main/assets/live-3.jsonc live-3.jsonc

最新调整:

  • 去除 number 频道号码
  • 变更 live.jsonc 为 /lives/live-2026-03-19.jsonc
  • 增加频道上的 children 字段,支持换源

1. 对于没有验证的直播地址

修改 channel 频道列表

{
    // ...
    "channel": [
        // ...
        {
            "channelType": "xxx", // 频道类型(分类名称)
            "player": "common", // 播放器 id,这里写上,下方的 channelList 中没有设置的就默认为这个值
            "channelList": [
              {
                "channelName": "香港卫视", // 频道名称 (需要唯一)
                "tvLogo": "", // logo 目前没用到,可以不写
                "number": 6, // 填写唯一的频道号码,用于数字换台 (废弃)
                "player": "common", // 播放器 id,这个上方已经内置了,只需要写 common
                "args": { // 播放参数,固定 liveUrl 即可
                  "liveUrl": "https://wwww.tv.com/playlist.m3u8?"
                }
              }
            ]
        }
    ]
}

注意上方的 liveUrl 只能是普通的 m3u8地址,并且没有带时间戳等相关的参数

2. 对于开发人员

有些直播地址是有验证参数的,需要在脚本中进行处理生成

增加自定义频道,修改 channel 配置

// 省略其他
{
  // ...
  "channel": [
    // ...
    {
      "channelType": "xx电视分类",
      "player": "custom", // 设置自定义播放 id
      "channelList": [
        // ...
        {
          "channelName": "xx电视",
          "tvLogo": "https://web.cmc.hebtv.com/cms/rmt0336/upload/Image/9/9tpklm/2025/07/18/30aaea69a1de46a881cef5d759d30b3e.png",
          "number": 23
        }
        // ...
      ]
    }
  ]
}

修改 player 配置

{
  "player": {
    "id": "custom", // 播放器 id,和上面定义的频道 player 参数一致
    "name": "simple", // 内置的播放器名称,做了特殊处理,默认写这个
    "script": { // 需要执行的 js 脚本
      "init": [ // 在网页初始化完成时候执行的 js 脚本
        "https://gitee.com/jdy2002/DongYuTvWeb/raw/master/app/src/main/assets/js/hebei/init.js"
      ],
      "play": [ // 响应播放事件执行的 js 脚本
        "https://gitee.com/jdy2002/DongYuTvWeb/raw/master/app/src/main/assets/js/hebei/play.js"
      ],
      "resume_pause": [] // 暂停恢复执行的 js 脚本,这里留空,因为内部已经做了处理了
    }
  }
}

编辑 js 脚本

不需要云服务器,在 gitee 上建一个仓库,上面脚本地址自己写上仓库中实际的地址即可,具体格式参照上面的

simple 播放器已经内置了 CryptoJS,所以这里就不需要引入了,直接使用即可

脚本中,{{channelName}} 会被替换成用户选择的频道名称,当然其他 args 参数也会被这样替换进入

内部已经关闭了跨域限制,可以直接请求

playLive 是内置的方法,可以直接调用传入地址进行播放

注意:使用fetch请求时,有些会检测Referer请求头,请设置X-Referer请求头,内部会进行处理, 请求头数据请使用 X-Body 添加到请求头中,这里的数据将作为 Body 发送,

init.js, 对应上面 init 执行的脚本

通过普通 fetch 发送请求

这种方式有限制,有些请求会检测 Referer 请求头,请设置自定义请求头 X-Referer, 推荐使用内置的 HttpUtil 发送请求

(function() {
    // 这里在播放地址上面加上需要的参数
    window.addLiveUrlQuery = function (obj) {
       let ts = parseInt(new Date().getTime() / (1000)) + (7200);
       // CryptoJS 已经是内置的,可以直接使用
       return obj.liveVideo[0].formats[0].url + "?t=" + ts + '&k=' + CryptoJS.MD5(obj.appCustomParams.movie.liveUri + obj.appCustomParams.movie.liveKey + ts);;
    }

    fetch("https://api.cmc.hebtv.com/scms/api/com/article/getArticleList?catalogId=32557&siteId=1", {
      "headers": {
        "accept": "application/json, text/javascript, */*; q=0.01",
        "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
        "sec-ch-ua": "\"Google Chrome\";v=\"143\", \"Chromium\";v=\"143\", \"Not A(Brand\";v=\"24\"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": "\"Windows\"",
        "sec-fetch-dest": "empty",
        "sec-fetch-mode": "cors",
        "sec-fetch-site": "same-site",
        // 如果不检测 Referer的话,可以正常写
        "X-Referer": "https://www.hebtv.com/" // X-Referer 会自动在请求头添加 Referer,防止被检测
        // 必须在设置了 X-Referer 之后,X-Body 才有效
        "X-Body": "" // 这里设置请求体数据
      },
      "body": null,
      "method": "GET"
    }).then(res => {
      return res.json()
    }).then(res => {
        const news = res.returnData.news
        window.channelList = news.map(item => {
            return {
                title: item.title,
                liveVideo: item.liveVideo,
                appCustomParams: item.appCustomParams
            }
        })

        // {{channelName}} 会被替换成频道名称,上面的 channel中的属性都会被传入到脚本中,这里可以进行自定义处理
        const channelItem = window.channelList.find(item => item.title === '{{channelName}}')
        const playUrl = window.addLiveUrlQuery(channelItem)
        // 初始化时机执行的,所以这里需要对当前播放的频道进行播放,play.js 不会在初始化时候调用生效
        playLive(playUrl)
    })
})();
使用 HttpUtil 发送请求

内置在 simple 播放器中的,可以直接使用,推荐使用这种方式发送请求

const response = await HttpUtil.post(`https://feiying.litenews.cn/api/v1/auth/exchange?t=${now}&s=${s}`, body, {
    headers: {
        "accept": "*",
        "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
        "content-type": "text/plain",
        "priority": "u=1, i",
        "sec-ch-ua": "\"Google Chrome\";v=\"143\", \"Chromium\";v=\"143\", \"Not A(Brand\";v=\"24\"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": "\"Windows\"",
        "sec-fetch-dest": "empty",
        "sec-fetch-mode": "cors",
        "sec-fetch-site": "cross-site",
        "Referer": "https://v.iqilu.com/"
    },
    responseType: 'text'
})
const result = JSON.parse(decrypt(response.data))
playLive(result.data)

HttpUtil 的定义参见 HttpUtil

play.js 处理播放

(function() {
    const channelItem = window.channelList.find(item => item.title === '{{channelName}}')
    const playUrl = window.addLiveUrlQuery(channelItem)
    playLive(playUrl)
})();

Base 播放器

对于加密的直播地址,需要使用 Base 播放器,直接通过浏览器加载来实现播放,去除播放器以外的节点,实现全屏播放。

init.js实现 全屏并去除其他无用样式进行初始化

play.js实现 直接使用 window.location.href 进行跳转

resume_pause.js实现 查找按钮并点击

配置参考

url 参数支持动态参数,使用 {{}} 方式传入

// player 配置
{
  "id": "guangxi",
  "name": "base", // 指定为 base
  "url": "https://tv.gxtv.cn/channel/channelivePlay_{{id}}.html", // url 支持动态参数
  // 设置指定的脚本
  "script": {
    "init": ["https://gitee.com/jdy2002/DongYuTvWeb/raw/master/app/src/main/assets/js/guangxi/init.js"],
    "play": ["https://gitee.com/jdy2002/DongYuTvWeb/raw/master/app/src/main/assets/js/guangxi/play.js"],
    "resume_pause": ["https://gitee.com/jdy2002/DongYuTvWeb/raw/master/app/src/main/assets/js/guangxi/resume_pause.js"]
  }
}

id 参数会注入到上面 url 的 {{id}} 中

// channel 配置
{
  "channelType": "广西",
  "player": "guangxi",
  "channelList": [
    {
      "channelName": "广西卫视",
      "args": {
        "id": "e7a7ab7df9fe11e88bcfe41f13b60c62"
      }
    },
    {
      "channelName": "综艺旅游",
      "args": {
        "id": "f3335975f9fe11e88bcfe41f13b60c62"
      }
    }
  ]
}

simple 播放器内置的 html 代码

simple_player.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Document</title>
    <style>
        body {
            background: #000000;
        }

        #video {
            width: 100vw;
            height: 100vh;
        }

        #loading {
            position: fixed;
            left: 0;
            top: 0;
            z-index: 99;
            width: 100vw;
            height: 100vh;
            font-size: 30px;
            font-weight: bold;
            color: white;
            display:flex;
            align-items: center;
            justify-content: center;
        }
    </style>
    <!-- 这里内部做了处理 -->
    <script src="../js/lib/dy-http-util.js"></script>
    <script src="../js/lib/dy-crypto-js.min.js"></script>
    <script src="../js/lib/dy-hls.min.js"></script>
</head>
<body>
<video autoplay id="video"></video>
<div class="loading-overlay" id="loading">
    加载中...请稍后
</div>
</body>

<script>
    const video = document.querySelector("#video")

    video.addEventListener('loadeddata', function() {
        hideLoading()
    })

    function hideLoading() {
        const loading = document.getElementById('loading');
        loading.style.display = 'none';
    }

    function resumeOrPause() {
        if (video.paused) {
            video.play();
        } else {
            video.pause();
        }
    }

    let hls = null;

    function playLive(url, headers) {
        video.volume = 1
        
        // 检查是否支持 HLS.js 且为 m3u8 文件
        if (Hls.isSupported() && url.includes('.m3u8')) {
            if (hls) {
                hls.destroy();
            }
            
            hls = new Hls({
                debug: false,
                xhrSetup: function(xhr, url) {
                    // xhr.setRequestHeader('X-Referer', headers['Referer'])
                    // 这里设置请求头
                    if (headers) {
                        for (const key in headers) {
                            xhr.setRequestHeader(key, headers[key]);
                        }
                    }
                }
            });
            
            hls.loadSource(url);
            hls.attachMedia(video);
            
            hls.on(Hls.Events.MANIFEST_PARSED, function() {
                video.play();
            });
            
            hls.on(Hls.Events.ERROR, function(event, data) {
                console.error('HLS Error:' + JSON.stringify(data));
                if (data.fatal) {
                    switch(data.type) {
                        case Hls.ErrorTypes.NETWORK_ERROR:
                            console.log('Network error, trying to recover');
                            hls.startLoad();
                            break;
                        case Hls.ErrorTypes.MEDIA_ERROR:
                            console.log('Media error, trying to recover');
                            hls.recoverMediaError();
                            break;
                        default:
                            console.log('Fatal error, destroying HLS instance');
                            hls.destroy();
                            break;
                    }
                }
            });
        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
            // iOS Safari 原生支持
            video.src = url;
            video.play();
        } else {
            // 其他格式直接播放
            video.src = url;
            video.play();
        }
    }
</script>
</html>

其他使用方法,请查看项目的 /app/src/main/assets 中的代码

配置多个源

具体配置参考 channel 配置

// channel 配置
{
  // ...
  "channelName": "example",
  // 设置多个源
  "children": [
    {
      "channelName": "example-1",
      "player": "base",
      "args": {
        "a": "b"
      }
    },
    {
      "channelName": "example-2",
      "player": "common",
      "args": {
        liveUrl: "http://example.com/live.m3u8"
      }
    }
  ]
}

截图

截图

截图

截图

注意

仅供学习交流,请勿用于商业用途

Explore related projects