济南免费做网站,wordpress安装提示数据库空,wordpress一键拨号,做内贸要在哪个网站找客户这篇是在上一篇的基础上写的#xff0c;这篇负责抖音作者详情页的视频转声音提取#xff0c;这篇需要用到后端。 本地启动后端后#xff0c;在控制台输入对应代码#xff0c;即可实现hover在封面上#xff0c;按d一键下载音频
控制台代码 // 获取作者的视频列表var liEle…这篇是在上一篇的基础上写的这篇负责抖音作者详情页的视频转声音提取这篇需要用到后端。 本地启动后端后在控制台输入对应代码即可实现hover在封面上按d一键下载音频
控制台代码
// 获取作者的视频列表var liElements document.querySelectorAll(ul[data-e2escroll-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为 68if (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?sz64domaindouyin.com
// grant none
// /UserScript(function() {use strict;// Your code here...// 目标节点var targetNode document.querySelector(ul[data-e2escroll-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-e2escroll-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为 68if (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)});}})();