将抖音视频转成MP3并下载
这篇是在上一篇的基础上写的,这篇负责抖音作者详情页的视频转声音提取,这篇需要用到后端。
本地启动后端后,在控制台输入对应代码,即可实现hover在封面上,按d一键下载音频
- 控制台代码
// 获取作者的视频列表var liElements = document.querySelectorAll('ul[data-e2e="scroll-list"] li');// 添加鼠标悬停事件监听器liElements.forEach(function(li) {li.addEventListener('mouseenter', function() {// 添加键盘按下事件监听器document.addEventListener('keydown', keydownHandler);});li.addEventListener('mouseleave', function() {// 移除键盘按下事件监听器document.removeEventListener('keydown', keydownHandler);});});// 处理键盘按下事件function keydownHandler(event) {// 判断按下的键是否为 'D' 键,keyCode为 '68'if (event.keyCode === 68) {// 获取下载链接var sourceTag = document.querySelector('.basePlayerContainer xg-video-container > video > source:nth-child(1)');const alt = document.querySelector('.basePlayerContainer').previousElementSibling.querySelector('img').getAttribute('alt');// 找到第一个冒号并截取之后的部分let contentAfterColon = alt.includes(':') ? alt.split(':').slice(1).join(':'):alt;// 去除所有的.和空格let resultString = contentAfterColon.replace(/[.\s]/g, '');// 如果最终结果为空,替换为'空'const name = resultString === '' ? '空' : resultString;// 提取src属性值var url = sourceTag.getAttribute('src');// 执行下载操作,这里使用一个假设的下载函数downloadFile(url, name);}}function downloadFile(url, name) {// 发送POST请求到后台接口fetch('http://localhost:3000/convert', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ videoUrl: url }),}).then((response) => response.blob()).then((blob) => {// 创建一个临时的<a>元素用于下载const a = document.createElement('a');const url = window.URL.createObjectURL(blob);a.href = url;a.download = name + '.mp3';// 触发点击事件以启动下载a.click();// 释放URL对象window.URL.revokeObjectURL(url);}).catch((error) => {console.error('Error:', error);alert('下载失败,原因:' + error)});
}
- 后端 node 代码
const express = require('express');
const axios = require('axios');
const ffmpeg = require('fluent-ffmpeg');
const fs = require('fs');
const path = require('path');
const cors = require('cors');
const app = express();app.use(express.json());
// 允许所有域的请求
app.use(cors());app.post('/convert', async (req, res) => {try {const { videoUrl } = req.body;if (!videoUrl) {return res.status(400).json({ error: 'Missing videoUrl parameter' });}const videoFileName = 'inputVideo.mp4';const audioFileName = 'outputAudio.mp3';// Download the video fileconst response = await axios.get(videoUrl, { responseType: 'arraybuffer' });fs.writeFileSync(videoFileName, Buffer.from(response.data));// Convert video to audio using ffmpegawait new Promise((resolve, reject) => {ffmpeg().input(videoFileName).audioCodec('libmp3lame').toFormat('mp3').on('end', () => resolve()).on('error', (err) => reject(err)).save(audioFileName);});// Send the converted audio file to the clientres.download(audioFileName, (err) => {if (err) {console.error(err);res.status(500).json({ error: 'Internal server error' });}// Clean up temporary filesfs.unlinkSync(videoFileName);fs.unlinkSync(audioFileName);});} catch (err) {console.error(err);res.status(500).json({ error: 'Internal server error' });}
});const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {console.log(`Server is running on port ${PORT}`);
});
如果不想用控制台,也可以用暴力猴,暴力猴脚本如下:
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 2024-01-12
// @description try to take over the world!
// @author You
// @match https://www.douyin.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=douyin.com
// @grant none
// ==/UserScript==(function() {'use strict';// Your code here...// 目标节点var targetNode = document.querySelector('ul[data-e2e="scroll-list"]');// 初始时的li数量var initialCount = targetNode.children.length;// 配置观察器的设置var config = { childList: true };// 观察器回调var callback = function(mutationsList, observer) {// 当前的li数量var currentCount = targetNode.children.length;// 检查li数量是否增加if (currentCount > initialCount) {// 执行你的函数addWatch();console.log('添加监听器')// 更新初始时的li数量initialCount = currentCount;}};// 创建一个观察器实例并传入回调函数var observer = new MutationObserver(callback);// 使用配置和目标节点开始观察observer.observe(targetNode, config);// 给所有 li 添加监听器function addWatch() {// 获取作者的视频列表var liElements = document.querySelectorAll('ul[data-e2e="scroll-list"] li');// 添加鼠标悬停事件监听器liElements.forEach(function(li) {li.addEventListener('mouseenter', function() {// 添加键盘按下事件监听器document.addEventListener('keydown', keydownHandler);});li.addEventListener('mouseleave', function() {// 移除键盘按下事件监听器document.removeEventListener('keydown', keydownHandler);});});}// 处理键盘按下事件function keydownHandler(event) {// 判断按下的键是否为 'D' 键,keyCode为 '68'if (event.keyCode === 68) {// 获取下载链接var sourceTag = document.querySelector('.basePlayerContainer xg-video-container > video > source:nth-child(1)');const alt = document.querySelector('.basePlayerContainer').previousElementSibling.querySelector('img').getAttribute('alt');// 找到第一个冒号并截取之后的部分let contentAfterColon = alt.includes(':') ?alt.split(':').slice(1).join(':'):alt;// 去除所有的.和空格let resultString = contentAfterColon.replace(/[.\s]/g, '');// 如果最终结果为空,替换为'空'const name = resultString === '' ? '空' : resultString;// 提取src属性值var url = sourceTag.getAttribute('src');// 执行下载操作,这里使用一个假设的下载函数downloadFile(url, name);}}function downloadFile(url, name) {// 发送POST请求到后台接口fetch('http://localhost:3000/convert', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ videoUrl: url }),}).then((response) => response.blob()).then((blob) => {// 创建一个临时的<a>元素用于下载const a = document.createElement('a');const url = window.URL.createObjectURL(blob);a.href = url;a.download = name + '.mp3';// 触发点击事件以启动下载a.click();// 释放URL对象window.URL.revokeObjectURL(url);}).catch((error) => {console.error('Error:', error);alert('下载失败,原因:' + error)});}})();
相关文章:
将抖音视频转成MP3并下载
这篇是在上一篇的基础上写的,这篇负责抖音作者详情页的视频转声音提取,这篇需要用到后端。 本地启动后端后,在控制台输入对应代码,即可实现hover在封面上,按d一键下载音频 控制台代码 // 获取作者的视频列表var liEle…...
C程序训练:与输入有关的错误
在录入程序时有时稍不注意就可能录入错误的字符导致程序运行结果出现错误,下面举例说明。 下面程序的运行结果是错的,但程序又没有错,到底问题出现在哪呢? #include <stdio.h> int main() {FILE *fp;int i, k, n;fpfopen(…...
制作 CentOS Stream9 的U盘系统启动盘
一、简述 注:请勿用于商用,如有版权纠纷,于博主无任何关系。(仅用于学习研究使用) 由于CentOs Linux 7和CentOs Stream8终止日期是2024年,需要将系统升级到最新版本的CentOs Stream9,下面是刻录系统盘的操…...
Vulnhub靶机:driftingblues 1
一、介绍 运行环境:Virtualbox 攻击机:kali(10.0.2.15) 靶机:driftingblues1(10.0.2.17) 目标:获取靶机root权限和flag 靶机下载地址:https://www.vulnhub.com/entr…...
CloudCompare——点云空间圆拟合
目录 1.概述2.软件实现3.完整操作4.算法源码5.相关代码 本文由CSDN点云侠原创,CloudCompare——点云空间圆拟合,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT生成的文章。 1.概述 CloudCompare软件中的To…...
解决POI报错POIXMLTypeLoader不存在的问题
问题: springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/apache/poi/POIXMLTypeLoaderat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet…...
关于rewriteBatchedStatements的源码分析
在之前的优惠券兑换码需求中,涉及批量写入问题,其中有一个关键的连接配置参数非常重要——rewriteBatchedStatements,当该值配置为true时,Statement将可能对批量插入sql进行重写。 何谓重写?原来提交的批量执行语句&a…...
自动化神器 Playwright 的 Web 自动化测试解决方案
1. 主流框架的认识 总结: 由于Selenium在3.x和4.x两个版本的迭代中并没有发生多大的变化,因此Selenium一统天下的地位可能因新框架的出现而变得不那么稳固。后续的Cypress、TestCafe、Puppeteer被誉为后Selenium时代Web UI自动化的三驾马车。但是由于这三…...
docker filebeat 将日志多级目录和多维json数据日志同步到es
注 使用的时候先调试调试配置,调试成功在尝试写入es,如果es写入失败就是es账户.密码/白名单.和index未创建的问题,细节可以留言 setup.template.priority 模板优先级 调整这个可以配置一台机器多个filebeat 容器启动 多级目录日志和多维josn日志结构 filebeat.inputs:- typ…...
【机器学习】模型参数优化工具:Optuna使用分步指南(附XGB/LGBM调优代码)
常用的调参方式和工具包 常用的调参方式包括网格搜索(Grid Search)、**随机搜索(Random Search)和贝叶斯优化(Bayesian Optimization)**等。 工具包方面,Scikit-learn提供了GridSearchCV和RandomizedSearchCV等用于网格搜索和随机搜索的工具。另外,有一…...
webview全屏处理,即插即用
去年双十一有个直播的需求,听起来很简单,技术也都很成熟,但是真的开始实现后,还是有不少坑的,首先第一个uc内核不支持webRTC协议,需要重新开发chrome内核的webview,其次webview全屏处理、悬浮窗…...
实录分享 | 央企大数据平台架构发展趋势与应用场景的介绍
分享嘉宾: 孟子涵-中国华能集团信息中心平台架构师 2021年华能就与Alluxio建立了合作,共同写了整个华能统一纳管的架构方案。这个方案我认为是现在我们在央企里边比较核心的一套体系,能让全集团所有我们认为重要的数字化资源实现真正的统一集…...
UE5 将类修改目录
有个需求,需要修改ue里面类的位置,默认在Public类下面,我想创建一个二级目录,将所有的类分好位置,方便查看。 上图为创建一个类所在的默认位置。 接下来,将其移动到一个新的目录中。 首先在资源管理器中找…...
GPT实战系列-ChatGLM3管理工具的API接口
GPT实战系列-ChatGLM3管理外部借力工具 用ChatGLM的工具可以实现很多查询接口和执行命令,外部工具该如何配置使用?如何联合它们实现大模型查询助手功能?例如调用工具实现股票信息查询,网络天气查询等助手功能。 LLM大模型相关文章…...
Python 列表、元组、字典区别
1.列表、元组和字典都是序列 2.列表字典可以修改和删除序列中的某个元素,而元组就是一个整体,不能修改和删除,一定要修改或删除的话,只能修改和删除整个元组。 3.既然元组不能删除和修改,有什么作用呢? 1…...
[足式机器人]Part2 Dr. CAN学习笔记 - Ch03 傅里叶级数与变换
本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-Ch03 傅里叶级数与变换 1. 三角函数的正交性2. 周期为 2 π 2\pi 2π的函数展开为傅里叶级数3. 周期为 2 L 2L 2L的函数展开4. 傅里叶级数的复数形式5. 从傅里叶级数推导傅里叶变换FT6. 总结 1. …...
你想使用域名访问一个ip的网页,你应该怎么办呢?
你想使用域名访问一个ip的网页,你应该怎么办呢? eg:你想用https://test.com/访问http://1.1.1.1/方法: eg:你想用https://test.com/访问http://1.1.1.1/ 方法: 1.首先,如果你是服务器的管理者,你需要在服务器的官网申请一个test.com的域名,然后在官网将域名映射到1.1.1.1上. …...
SAP存放状态的几个常用表
SAP存放状态的几个常用表 在sap中,包括订单、项目、计划、设备主数据等,存在审批流程的业务单据,这些业务对象都会有状态的属性,用来控制和约束该业务当前的操作。 主要的表 JEST:存放了该对象编号的当前状态 JCDS…...
AUTO SEG-LOSS SEARCHING METRIC SURROGATES FOR SEMANTIC SEGMENTATION
AUTO SEG-LOSS: 搜索度量替代语义分割 论文链接:https://arxiv.org/abs/2010.07930 项目链接:https://github.com/fundamentalvision/Auto-Seg-Loss ABSTRACT 设计合适的损失函数是训练深度网络的关键。特别是在语义分割领域,针对不同的场…...
openssl3.2 - 官方demo学习 - 索引贴
文章目录 openssl3.2 - 官方demo学习 - 索引贴概述笔记工程的搭建和调试环境BIOBIO - client-arg.cBIO - client-conf.cBIO - saccept.cBIO - sconnect.cBIO - server-arg.cBIO - server-cmod.cBIO - server-conf.cBIO - 总结certsciphercipher - aesccm.ccipher - aesgcm.ccip…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...
