当前位置: 首页 > news >正文

将抖音视频转成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并下载

这篇是在上一篇的基础上写的&#xff0c;这篇负责抖音作者详情页的视频转声音提取&#xff0c;这篇需要用到后端。 本地启动后端后&#xff0c;在控制台输入对应代码&#xff0c;即可实现hover在封面上&#xff0c;按d一键下载音频 控制台代码 // 获取作者的视频列表var liEle…...

C程序训练:与输入有关的错误

在录入程序时有时稍不注意就可能录入错误的字符导致程序运行结果出现错误&#xff0c;下面举例说明。 下面程序的运行结果是错的&#xff0c;但程序又没有错&#xff0c;到底问题出现在哪呢&#xff1f; #include <stdio.h> int main() {FILE *fp;int i, k, n;fpfopen(…...

制作 CentOS Stream9 的U盘系统启动盘

一、简述 注:请勿用于商用&#xff0c;如有版权纠纷&#xff0c;于博主无任何关系。&#xff08;仅用于学习研究使用&#xff09; 由于CentOs Linux 7和CentOs Stream8终止日期是2024年&#xff0c;需要将系统升级到最新版本的CentOs Stream9&#xff0c;下面是刻录系统盘的操…...

Vulnhub靶机:driftingblues 1

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;driftingblues1&#xff08;10.0.2.17&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entr…...

CloudCompare——点云空间圆拟合

目录 1.概述2.软件实现3.完整操作4.算法源码5.相关代码 本文由CSDN点云侠原创&#xff0c;CloudCompare——点云空间圆拟合&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫与GPT生成的文章。 1.概述 CloudCompare软件中的To…...

解决POI报错POIXMLTypeLoader不存在的问题

问题&#xff1a; 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的源码分析

在之前的优惠券兑换码需求中&#xff0c;涉及批量写入问题&#xff0c;其中有一个关键的连接配置参数非常重要——rewriteBatchedStatements&#xff0c;当该值配置为true时&#xff0c;Statement将可能对批量插入sql进行重写。 何谓重写&#xff1f;原来提交的批量执行语句&a…...

自动化神器 Playwright 的 Web 自动化测试解决方案

1. 主流框架的认识 总结&#xff1a; 由于Selenium在3.x和4.x两个版本的迭代中并没有发生多大的变化&#xff0c;因此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)**等。 工具包方面&#xff0c;Scikit-learn提供了GridSearchCV和RandomizedSearchCV等用于网格搜索和随机搜索的工具。另外&#xff0c;有一…...

webview全屏处理,即插即用

去年双十一有个直播的需求&#xff0c;听起来很简单&#xff0c;技术也都很成熟&#xff0c;但是真的开始实现后&#xff0c;还是有不少坑的&#xff0c;首先第一个uc内核不支持webRTC协议&#xff0c;需要重新开发chrome内核的webview&#xff0c;其次webview全屏处理、悬浮窗…...

实录分享 | 央企大数据平台架构发展趋势与应用场景的介绍

分享嘉宾&#xff1a; 孟子涵-中国华能集团信息中心平台架构师 2021年华能就与Alluxio建立了合作&#xff0c;共同写了整个华能统一纳管的架构方案。这个方案我认为是现在我们在央企里边比较核心的一套体系&#xff0c;能让全集团所有我们认为重要的数字化资源实现真正的统一集…...

UE5 将类修改目录

有个需求&#xff0c;需要修改ue里面类的位置&#xff0c;默认在Public类下面&#xff0c;我想创建一个二级目录&#xff0c;将所有的类分好位置&#xff0c;方便查看。 上图为创建一个类所在的默认位置。 接下来&#xff0c;将其移动到一个新的目录中。 首先在资源管理器中找…...

GPT实战系列-ChatGLM3管理工具的API接口

GPT实战系列-ChatGLM3管理外部借力工具 用ChatGLM的工具可以实现很多查询接口和执行命令&#xff0c;外部工具该如何配置使用&#xff1f;如何联合它们实现大模型查询助手功能&#xff1f;例如调用工具实现股票信息查询&#xff0c;网络天气查询等助手功能。 LLM大模型相关文章…...

Python 列表、元组、字典区别

1.列表、元组和字典都是序列 2.列表字典可以修改和删除序列中的某个元素&#xff0c;而元组就是一个整体&#xff0c;不能修改和删除&#xff0c;一定要修改或删除的话&#xff0c;只能修改和删除整个元组。 3.既然元组不能删除和修改&#xff0c;有什么作用呢&#xff1f; 1…...

[足式机器人]Part2 Dr. CAN学习笔记 - Ch03 傅里叶级数与变换

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;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中&#xff0c;包括订单、项目、计划、设备主数据等&#xff0c;存在审批流程的业务单据&#xff0c;这些业务对象都会有状态的属性&#xff0c;用来控制和约束该业务当前的操作。 主要的表 JEST&#xff1a;存放了该对象编号的当前状态 JCDS…...

AUTO SEG-LOSS SEARCHING METRIC SURROGATES FOR SEMANTIC SEGMENTATION

AUTO SEG-LOSS: 搜索度量替代语义分割 论文链接&#xff1a;https://arxiv.org/abs/2010.07930 项目链接&#xff1a;https://github.com/fundamentalvision/Auto-Seg-Loss ABSTRACT 设计合适的损失函数是训练深度网络的关键。特别是在语义分割领域&#xff0c;针对不同的场…...

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…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...