给哔哩哔哩bilibili电脑版做个手机遥控器

news2024/11/28 16:35:38

前言

bilibili电脑版可以在电脑屏幕上观看bilibili视频。然而,电脑版的bilibili不能通过手机控制视频翻页和调节音量,这意味着观看视频时需要一直坐在电脑旁边。那么,有没有办法制作一个手机遥控器来控制bilibili电脑版呢?

首先,bilibili电脑版支持快捷键,可以通过一些快捷键来控制视频播放。例如,按下空格键可以控制视频的播放和暂停。

既然快捷键可以控制视频,那么我们的思路就很清晰了。可以在电脑上搭建一个HTTP服务器,部署一个遥控器样式的网页,上面放置一些简单的按钮。用户打开网页后,点击这些按钮,服务器端就会模拟用户点击键盘来实现相应的操作。

前后台代码实现

说干就干, 开始动手实现这个手机版bilibili遥控器, 语言方面我们选择使用NodeJS来搭建我们的服务器, 先写前端UI:

整体的网页框架

<html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<body>
    ...
</body>
<script>
    ...
</script>
</html>
  • <meta charset="utf-8">: 指定文档的字符编码为UTF-8。
  • <meta name="viewport" content="width=device-width, initial-scale=1" />: 使页面在移动设备上适应屏幕宽度,并初始缩放比例为1。

遥控器的按钮:

<button data-action="up" style="margin-bottom: 30px;width: 100%;height: 110px;">音量+</button>
<button data-action="down" style="margin-bottom: 30px;width: 100%;height: 110px;">音量-</button>
<button data-action="previous" style="margin-bottom: 30px;width: 100%;height: 110px;">上一个</button>
<button data-action="next" style="margin-bottom: 30px;width: 100%;height: 110px;">下一个</button>
<button data-action="pauseOrPlay" style="margin-bottom: 30px;width: 100%;height: 110px;">暂停/播放</button>

每个按钮都有一个 data-action 属性,用于定义按钮的动作。

按钮的样式通过 style 属性设置,按钮高度110px,宽度100%,且每个按钮的底部都有30px的间距。

Javascript代码

document.querySelectorAll('button[data-action]').forEach(button => {
    button.addEventListener('click', () => {
        const action = button.getAttribute('data-action');
        fetch(`${window.location.origin}/${action}`)
            .then(response => response.json())
            .then(data => {
                console.log(data);
            })
            .catch(error => {
                alert('Error fetching data:', error);
            });
    });
});

首先代码中会选择所有带有 data-action 属性的按钮。

为每个按钮添加点击事件监听器。

点击按钮后,会获取按钮的 data-action 属性值,并发起一个fetch请求

整体的网页代码

整体的网页代码如下:

<html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />

<body>
    <button data-action="up" style="margin-bottom: 30px;width: 100%;height: 110px;">音量+</button>
    <br>
    <button data-action="down" style="margin-bottom: 30px;width: 100%;height: 110px;">音量-</button>
    <br>
    <button data-action="previous" style="margin-bottom: 30px;width: 100%;height: 110px;">上一个</button>
    <br>
    <button data-action="next" style="margin-bottom: 30px;width: 100%;height: 110px;">下一个</button>
    <br>
    <button data-action="pauseOrPlay" style="margin-bottom: 30px;width: 100%;height: 110px;">暂停/播放</button>
    <br>
</body>

<script>
    document.querySelectorAll('button[data-action]').forEach(button => {
        button.addEventListener('click', () => {
            const action = button.getAttribute('data-action');
            fetch(`${window.location.origin}/${action}`)
                .then(response => response.json())
                .then(data => {
                    console.log(data);
                })
                .catch(error => {
                    alert('Error fetching data:', error);
                });
        });
    });
</script>

</html>

预览效果

网页在手机浏览器里打开的效果如下图所示:

后端HTTP服务器实现

剩下的就是服务端了, 主要用来接受http请求, 触发不同的键盘事件即可.

整体代码

const path = require("path");
const ks = require('node-key-sender');
const express = require('express');
const app = express();
const port = 3000;

const actions = {
  next: () => ks.sendKey('down'),
  previous: () => ks.sendKey('up'),
  up: () => ks.sendCombination(['shift', 'up']),
  down: () => ks.sendCombination(['shift', 'down']),
  pauseOrPlay: () => ks.sendKey('space')
};

Object.keys(actions).forEach(action => {
  app.get(`/${action}`, async (req, res) => {
    try {
      await actions[action]();
      res.json({ success: true, message: `${action} action completed` });
    } catch (error) {
      res.status(500).json({ success: false, message: `Error performing ${action} action`, error });
    }
  });
});

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'index.html'));
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

代码解释

引入模块

const path = require("path");
const ks = require('node-key-sender');
const express = require('express');

node-key-sender: 这个模块用于发送模拟键盘按键事件。

express: 用于创建Web服务器的Node.js框架。

创建Express应用和设置端口

const app = express();
const port = 3000;


定义动作(Actions)对象

const actions = {
  next: () => ks.sendKey('down'),
  previous: () => ks.sendKey('up'),
  up: () => ks.sendCombination(['shift', 'up']),
  down: () => ks.sendCombination(['shift', 'down']),
  pauseOrPlay: () => ks.sendKey('space')
};

这里定义了五个动作,每个动作对应一个键盘事件。

创建路由

Object.keys(actions).forEach(action => {
  app.get(`/${action}`, async (req, res) => {
    try {
      await actions[action]();
      res.json({ success: true, message: `${action} action completed` });
    } catch (error) {
      res.status(500).json({ success: false, message: `Error performing ${action} action`, error });
    }
  });
});


使用 Object.keys(actions) 获取所有动作的名称,并为每个动作创建一个对应的路由。

处理请求时,调用相应的动作,并返回JSON格式的响应。

返回静态网页

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'index.html'));
});

这个路由将根路径 (/) 的请求返回 index.html 文件。

启动服务器

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

服务器监听指定端口(这里是3000),并在启动时输出提示信息。

添加上package.json文件

package.json文件用来描述dependencies信息

{
  "name": "bilibili-remote-control",
  "version": "1.0.0",
  "description": "Bilibili遥控器",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "express": "^4.17.1",
    "node-key-sender": "^1.0.11"
  }
}

运行手机遥控器

整个代码就完成了, 现在可以启动遥控器了:

装上dependencies

npm install

运行遥控器

npm run start

可以看到服务器已经启动起来了

手机浏览器里打开192.168.x.x开头的网页, 然后运行bilibili桌面版, 即可在手机里面控制bilibili的播放了, 再也不用坐在电脑屏幕跟前了.

总结

以上便是给整个bilibili手机版遥控器介绍, 相关代码已经发布到CSDN, 可以直接访问: bilibili-remote-controller:Bilibili电脑版手机遥控器 - GitCode

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222384.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot+Vue+uniapp的时间管理小程序的详细设计和实现(源码+lw+部署文档+讲解等)

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不…

【文件加密系统】华企盾DSC服务程序启动失败解决办法

问题原因&#xff1a; 1.sa账户密码错误导致连接数据数据库失败无法启动DSC服务 解决方法&#xff1a; 用windows身份验证进入数据库更改sa用户密码&#xff1a;安全性>登录名>sa>右键属性>更改密码 ※如果显示请输入秘钥更改&#xff0c;使用更改完密码的sa账户登…

从0开始深度学习(16)——暂退法(Dropout)

上一章的过拟合是由于数据不足导致的&#xff0c;但如果我们有比特征多得多的样本&#xff0c;深度神经网络也有可能过拟合 1 扰动的稳健性 经典泛化理论认为&#xff0c;为了缩小训练和测试性能之间的差距&#xff0c;应该以简单的模型为目标&#xff0c;即模型以较小的维度的…

机器学习与神经网络:科技的星辰大海

前提 近日&#xff0c;2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者&#xff0c;这是历史上首次出现这样的情况。这项奖项原本只授予对自然现象和物质的物理学研究作出重大贡献的科学家&#xff0c;如今却将全球范围内对机器学习和神经网络的研究和开发作为了一…

RSocket vs WebSocket:Spring Boot 3.3 中的两大实时通信利器

RSocket vs WebSocket&#xff1a;Spring Boot 3.3 中的两大实时通信利器 随着现代互联网应用的不断发展&#xff0c;实时通信已经成为许多应用程序不可或缺的功能。无论是社交网络、在线游戏还是数据监控系统&#xff0c;实时通信都能提供快速、无缝的信息交换。而实现实时通…

“主升筹码”,底部建仓信号+主升加仓位置,不错过任何行情

使用技巧 指标分为主图和副图 其中&#xff0c;主图主升筹码信号较多&#xff0c;副图的信号较少。这里&#xff0c;我说一个选股思路&#xff0c;就是底部主升筹码共振进场&#xff0c;上升过程中主图信号当作加仓信号。 选股&#xff0c;提供一个主升筹码共振选股&#xff0…

Redis 5.0 安装配置(Windows)

Redis 5.0之后支持Redis Stream等功能 下载地址&#xff1a;Releases tporadowski/redis GitHub 点击运行redis-server.exe 此外&#xff1a;Redis 6.0及以后版本目前都没有Windows版

【越狱插件】内网穿透 frpc、frps插件

内网穿透、frp、frpc、frps https://zhaoboy9692.github.io/repo 越狱源 https://zhaoboy9692.github.io/repo 苦于在ios越狱下没有frp穿透使用 特地开发了的越狱插件 基于最新frp0.48编译 ios14.6测试没问题 有问题及时反馈

ubuntu中使用cmake编译报错No CMAKE_CXX_COMPILER could be found.的解决方法

ubuntu中使用cmake编译报错No CMAKE_CXX_COMPILER could be found.的解决方法 No CMAKE_CXX_COMPILER could be found.Could NOT find CUDA (missing: CUDA_NVCC_EXECUTABLE CUDA_CUDART_LIBRARY)Could not find a package configuration file provided by "OpenCV" …

【SQL|大数据|数据清洗|过滤】where条件中 “ != “ 和 “ NOT IN() ” 对NULL的处理

对数据进行清洗过滤的时候&#xff0c;NULL往往是一个很特殊的存在&#xff0c;对NULL值的存在通常有以下三种方式 1、保留NULL 2、过滤掉NULL 3、将NULL替换为其他符合业务需求的默认常量 下面是一些常用处理NULL的方式&#xff1a; 如下图所示数据源&#xff1a; car_vin&…

android openGL ES详解——缓冲区VBO/VAO/EBO/FBO

目录 一、缓冲区对象概念 二、分类 三、顶点缓冲区对象VBO 1、概念 2、为什么使用VBO 3、如何使用VBO 生成缓冲区对象 绑定缓冲区对象 输入缓冲区数据 更新缓冲区中的数据 删除缓冲区 4、VBO应用 四、顶点数组对象VAO 1、概念 2、为什么使用VAO 3、如何使用VAO…

ai修复照片工具哪个好?在线将模糊图像变清晰就用它

最近想尝试学习一下复古照片的拍摄风格&#xff0c;一波翻箱倒柜的操作翻出了以前家里拍的照片&#xff0c;却发现有些照片出现了氧化褪色&#xff0c;看不清原本图像的情况。 想看清晰一点的照片却找不到原本的底片&#xff0c;没办法再次冲洗新的相纸出来&#xff0c;该怎么…

Generative AI project lifecycle 生成式人工智能项目的全生命周期

这篇文章&#xff0c;你将学习到开发和部署一个由LLM驱动的应用程序所需的技术。在你将了解一个生成式AI项目的全生命周期&#xff0c;这可以帮助指导你完成这项工作。这个框架映射出了从概念到发布所需的任务。这里有一个整体生命周期的图表。我们将逐个阶段地讨论它。 在任何…

一文说明MySQL索引

最近研究了一下关于MySQL索引方面的面试题&#xff0c;以及可能拓展的问题&#xff0c;与大家分享 索引 在MySQL中&#xff0c;常见的索引类型包括以下几种&#xff1a; 普通索引&#xff08;INDEX&#xff09; &#xff1a;这是最基本的索引类型&#xff0c;可以包含一个或多…

基于springboot+vue实现的助学兼职系统(源码+L文+ppt)4-092

基于springbootvue实现的助学兼职系统&#xff08;源码L文ppt&#xff09;4-092 第4章 系统设计 4.1 总体功能设计 一般学生、招聘公司和管理者都需要登录才能进入助学兼职系统&#xff0c;使用者登录时会在后台判断使用的权限类型&#xff0c;包括一般使用者和管理者,一般使…

探索 Python 中的 XML 转换利器:xml2dict

文章目录 **探索 Python 中的 XML 转换利器&#xff1a;xml2dict**一、背景介绍二、xml2dict 是什么&#xff1f;三、如何安装 xml2dict&#xff1f;四、基本用法五、实际应用场景六、常见问题及解决方案七、总结 探索 Python 中的 XML 转换利器&#xff1a;xml2dict 一、背景…

构建智能暖箱监控系统:基于C#和WPF的完整指南

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

鸿蒙前端-1. 层叠效果

代码Stack&#xff08;{alignContent&#xff1a;Alignment.Center}&#xff09;{ Item1&#xff08;&#xff09; Item2&#xff08;&#xff09; Item3&#xff08;&#xff09;} 默认是居中对齐&#xff0c;后面的Item的优先级比前面的要高。 特点&#xff1a;代码简洁&…

stm32实现esp8266连接到TCP服务器(二)

1.2 连接到TCP Server 1.2.1 使用网络助手&#xff0c;设立TCP服务器 ​ 编辑 1.2.2 连接服务器 ATCIPSTART"TCP","192.168.1.18",8080 //指令&#xff0c;注意双引号逗号都要半角(英文)输入 CONNECT //结果&#xff1a;成功 OK //结果&#xff1a;成功 …

08 实战:色彩空间展示(本程序以视频为主)

程序效果如下: 我在这里讲解RGB和YCbCr的原理: 一、RGB颜色空间 1.1 基本概念 RGB颜色空间是一种最基础和常用的颜色表示方式,它基于人眼感知色彩的三原色原理。RGB分别代表: R(Red):红色G(Green):绿色B(Blue):蓝色通过这三种基本颜色的不同组合,可以产生人眼…