批量提取某音文案

简介: 本文介绍了批量提取文案的思路, 以及操作过程中的问题的处理方法, 并给了详细的参考代码, 以及对应的文档.

牙叔教程 简单易懂

我想学习某个人的文案, 怎么把它的文案全下载下来?

  1. 批量下载视频和音频
  2. 批量音频转文字

下载视频和音频

我在github找到的是这个仓库

https://github.com/Johnserf-Seed/TikTokDownload

经过实际测试, 可以使用, 只是失败的频率略高.

获取用户信息的时候, 尝试了5次才正确获取到用户信息,

只有获取到用户信息, 才能下载到视频;

虽然失败的概率有点高, 但是也仅是要多按几下 ↑ 和 回车键, 也不费啥事.

如果, 填写了cookie, 那么成功率大大提高, 不懂的话就看仓库的 issue.

这是下载好的视频和音频, 可以看到mp4和mp3的后缀名,

音频是直接下载下来的, 不是后期提取的.

文件 conf.ini 默认是不下载音频的, 所以要改一下.

music后面默认是no, 改成yes

[music]

# 视频原声保存(yes|no)

music = yes

其他的就照着README.md做就可以了


语音转文字

一共三种方案

  • 某讯
  • 微软
  • 有道

某讯

我看了一下某讯的价格, 70块30个小时,


微软

微软也有语音转文字的服务, 就是要绑卡, 绑卡的话, 某宝是几十块左右;


网易

网易, 他是2块钱一个小时, 这个就很人性化,

某讯开始就是30个小时, 我又用不了那么多, 至少我现在用不了.

批量自动化的时候, 你才需要买它, 你单独转的话, 可以直接使用

网易见外 https://jianwai.youdao.com/index/0

网易见外不用花一分钱, 但是依然很好用


那么今天给大家试试两种方案

微软

如果你没有卡, 可以去某宝搞;

如果你不会创建微软的服务, 可以看这个教程

文本转语音-微软Azure-一步一步教你从注册到使用

https://mp.weixin.qq.com/s/ycc35s51W0_4-raoF-fsMw


我们要把音频转文字, 所以选择第二个, 脱机字幕

他的文档有代码, 直接复制黏贴就可以使用了

代码在此

https://learn.microsoft.com/zh-cn/azure/cognitive-services/speech-service/get-started-speech-to-text?pivots=programming-language-javascript&tabs=windows%2Cterminal

下面是我的代码例子

语音转文字, 分两步

  • mp3转wav
  • wav转文字

// 此示例支持最多 30 秒的音频。

const fs = require("fs");

const sdk = require("microsoft-cognitiveservices-speech-sdk");

const { exec } = require("child_process");


const { secretKey: YourSubscriptionKey, region: YourServiceRegion, mp3FilePath } = require("./config.js");


let wavFilePath = mp3FilePath.replace(".mp3", ".wav");

let mp3ToWavCmd = `ffmpeg -i "${mp3FilePath}" "${wavFilePath}"`;


const speechConfig = sdk.SpeechConfig.fromSubscription(YourSubscriptionKey, YourServiceRegion);

speechConfig.speechRecognitionLanguage = "zh-CN";


async function recognizeSpeechFromFile() {

 let speechRecognizer;

 try {

   // Convert MP3 to WAV

   await new Promise((resolve, reject) => {

     exec(mp3ToWavCmd, (error) => {

       if (error) {

         console.error(`Error converting MP3 to WAV: ${error.message}`);

         reject(error);

       } else {

         console.log("MP3 file converted to WAV successfully.");

         resolve();

       }

     });

   });


   const audioConfig = sdk.AudioConfig.fromWavFileInput(fs.readFileSync(wavFilePath));

   speechRecognizer = new sdk.SpeechRecognizer(speechConfig, audioConfig);

   await new Promise((resolve, reject) => {

     speechRecognizer.recognizeOnceAsync((result) => {

       switch (result.reason) {

         case sdk.ResultReason.RecognizedSpeech:

           console.log(`RECOGNIZED: Text=${result.text}`);

           resolve(result.text);

           break;

         case sdk.ResultReason.NoMatch:

           console.log("NOMATCH: Speech could not be recognized.");

           reject("NOMATCH");

           break;

         case sdk.ResultReason.Canceled: {

           const cancellation = sdk.CancellationDetails.fromResult(result);

           console.log(`CANCELED: Reason=${cancellation.reason}`);


           if (cancellation.reason === sdk.CancellationReason.Error) {

             console.log(`CANCELED: ErrorCode=${cancellation.ErrorCode}`);

             console.log(`CANCELED: ErrorDetails=${cancellation.errorDetails}`);

             console.log("CANCELED: Did you set the speech resource key and region values?");

           }

           reject("CANCELED");

           break;

         }

       }

     });

   });

 } catch (error) {

   console.error("Error during recognition:", error);

 } finally {

   if (speechRecognizer) {

     speechRecognizer.close();

   }

 }

}


recognizeSpeechFromFile();



不过, 还是应该看看文档再动手,

这是微软文字转语音的文档

https://learn.microsoft.com/zh-cn/azure/cognitive-services/speech-service/captioning-concepts?pivots=programming-language-javascript


上面的代码只支持30s, 如果改成这种订阅式的代码, 就支持更长时间了

我们将订阅从 SpeechRecognizer 发送的事件:


recognizing:事件信号,包含中间识别结果。

recognized:包含最终识别结果的事件信号,指示成功的识别尝试。

sessionStopped:事件信号,指示识别会话的结束(操作)。

canceled:事件信号,包含已取消的识别结果。 这些结果指示因直接取消请求而取消的识别尝试。 或者,它们指示传输或协议失败。

speechRecognizer.recognizing = (s, e) => {

   console.log(`RECOGNIZING: Text=${e.result.text}`);

};


speechRecognizer.recognized = (s, e) => {

   if (e.result.reason == sdk.ResultReason.RecognizedSpeech) {

       console.log(`RECOGNIZED: Text=${e.result.text}`);

   }

   else if (e.result.reason == sdk.ResultReason.NoMatch) {

       console.log("NOMATCH: Speech could not be recognized.");

   }

};


speechRecognizer.canceled = (s, e) => {

   console.log(`CANCELED: Reason=${e.reason}`);


   if (e.reason == sdk.CancellationReason.Error) {

       console.log(`"CANCELED: ErrorCode=${e.errorCode}`);

       console.log(`"CANCELED: ErrorDetails=${e.errorDetails}`);

       console.log("CANCELED: Did you set the speech resource key and region values?");

   }


   speechRecognizer.stopContinuousRecognitionAsync();

};


speechRecognizer.sessionStopped = (s, e) => {

   console.log("\n    Session stopped event.");

   speechRecognizer.stopContinuousRecognitionAsync();

};


下载的数据

mp4 + mp3 + txt

语音转的文字

这是一个5分钟的电影解说, 1412个字,

如果是小说, 估计字数得翻倍, 这个是电影, 有一些时间是放的电影片段, 没有台词.


ffmpge

由于微软默认支持wav, 所以我们需要转换语音格式,  把mp3转成wav,

因此, 需要在电脑上安装 FFMPEG, 不会装的可以百度 Windows 10系统下安装FFmpeg教程详解

ffmpeg使用注意事项

  • 如果文件存在, 那么命令会卡住

网易

长语音转写文档

https://ai.youdao.com/DOCSIRMA/html/%E8%AF%AD%E9%9F%B3%E8%AF%86%E5%88%ABASR/API%E6%96%87%E6%A1%A3/%E9%95%BF%E8%AF%AD%E9%9F%B3%E8%BD%AC%E5%86%99%E6%9C%8D%E5%8A%A1/%E9%95%BF%E8%AF%AD%E9%9F%B3%E8%BD%AC%E5%86%99%E6%9C%8D%E5%8A%A1-API%E6%96%87%E6%A1%A3.html


创建应用时, 选择 长语音转写


网易文档中的错误

这个sliceId是 大写的i (爱),

但是他这个文档里是小写的l (矮楼)


文档中的响应结果, 是写文档的人复制黏贴的.

比如, 这几张响应结果, msg都是sucess


实际上, msg的值都是 null


文件上传的时候, 这里是字节数组, 而不是text

你就说这样写文档快不快吧, 类型全是text


网易长语音转文本的代码

const fs = require("fs");

const axios = require("axios");

const path = require("path");

const crypto = require("crypto");

const FormData = require("form-data");

const util = require("util");

const { wangyi } = require("./config.js");

const stat = util.promisify(fs.stat);


async function getFileSize(filePath) {

 try {

   const stats = await stat(filePath);

   const fileSizeInBytes = stats.size;

   console.log(`文件大小: ${fileSizeInBytes} 字节`);

   return fileSizeInBytes;

 } catch (err) {

   console.error("发生错误:", err);

 }

}


async function wangYiRcognizeSpeechFromFile(audioFilePath) {

 let fileName = path.basename(audioFilePath);

 // 请在这里设置您的应用ID和应用密钥

 const appKey = wangyi.appKey;

 const appSecret = wangyi.secretKey;

 let fileSize = await getFileSize(audioFilePath);

 let salt = uuidv4();

 let curtime = Math.floor(Date.now() / 1000);

 let sign = crypto

   .createHash("sha256")

   .update(appKey + salt + curtime + appSecret)

   .digest("hex");


 let formData = new FormData();

 formData.append("salt", salt);

 formData.append("type", 1);

 formData.append("appKey", appKey);

 formData.append("sliceNum", "1");

 formData.append("name", fileName);

 formData.append("fileSize", fileSize);

 formData.append("curtime", curtime);

 formData.append("langType", "zh-CHS");

 formData.append("sign", sign);

 formData.append("signType", "v4");

 formData.append("format", "mp3");

 formData.append("noitn", 1);


 const prepareResponse = await axios.post("http://openapi.youdao.com/api/audio/prepare", formData, { headers: formData.getHeaders() });


 if (prepareResponse.data.errorCode !== "0") {

   throw new Error(`Prepare failed: ${prepareResponse.data.msg}`);

 }

 console.log("准备上传");

 console.log(prepareResponse.data);

 const taskid = prepareResponse.data.result;

 formData = new FormData();

 formData.append("q", taskid);

 formData.append("appKey", appKey);

 salt = uuidv4();


 formData.append("salt", salt);

 formData.append("curtime", curtime);


 sign = crypto

   .createHash("sha256")

   .update(appKey + salt + curtime + appSecret)

   .digest("hex");


 formData.append("sign", sign);

 formData.append("signType", "v4");

 formData.append("sliceId", "1");

 // 判断文件是否存在

 if (!fs.existsSync(audioFilePath)) {

   throw new Error(`File not found: ${audioFilePath}`);

 }

 // 打印文件大小

 console.log(`文件大小: ${fs.statSync(audioFilePath).size} 字节`);

 formData.append("file", fs.readFileSync(audioFilePath), { contentType: "audio/mp3", filename: fileName });

 formData.append("type", "1");


 const uploadResponse = await axios.post("http://openapi.youdao.com/api/audio/upload", formData, { headers: formData.getHeaders() });


 if (uploadResponse.data.errorCode !== "0") {

   throw new Error(`Upload failed: ${uploadResponse.data.msg}`);

 }

 console.log("上传文件");

 console.log(uploadResponse.data);

 /* -------------------------------------------------------------------------- */

 formData = new FormData();

 formData.append("q", taskid);

 formData.append("appKey", appKey);

 salt = uuidv4();

 formData.append("salt", salt);

 curtime = Math.floor(Date.now() / 1000);

 formData.append("curtime", curtime);

 sign = crypto

   .createHash("sha256")

   .update(appKey + salt + curtime + appSecret)

   .digest("hex");


 formData.append("sign", sign);

 formData.append("signType", "v4");


 const mergeResponse = await axios.post("http://openapi.youdao.com/api/audio/merge", formData, { headers: formData.getHeaders() });


 if (mergeResponse.data.errorCode !== "0") {

   throw new Error(`Merge failed: ${mergeResponse.data.msg}`);

 }

 console.log("合并文件");

 console.log(mergeResponse.data);

 // process.exit(0);


 let progressResponse;

 do {

   await new Promise((resolve) => setTimeout(resolve, 60 * 1000));

   formData = new FormData();

   formData.append("q", taskid);

   formData.append("appKey", appKey);

   salt = uuidv4();

   formData.append("salt", salt);

   curtime = Math.floor(Date.now() / 1000);

   formData.append("curtime", curtime);

   sign = crypto

     .createHash("sha256")

     .update(appKey + salt + curtime + appSecret)

     .digest("hex");


   formData.append("sign", sign);

   formData.append("signType", "v4");

   progressResponse = await axios.post("http://openapi.youdao.com/api/audio/get_progress", formData, { headers: formData.getHeaders() });

   console.log("获取进度");

   console.log(progressResponse.data);

 } while (progressResponse.data.result[0].status !== "9");


 formData = new FormData();

 formData.append("q", taskid);

 formData.append("appKey", appKey);

 salt = uuidv4();

 formData.append("salt", salt);

 curtime = Math.floor(Date.now() / 1000);

 formData.append("curtime", curtime);

 sign = crypto

   .createHash("sha256")

   .update(appKey + salt + curtime + appSecret)

   .digest("hex");


 formData.append("sign", sign);

 formData.append("signType", "v4");


 const resultResponse = await axios.post("http://openapi.youdao.com/api/audio/get_result", formData, { headers: formData.getHeaders() });


 if (resultResponse.data.errorCode !== "0") {

   throw new Error(`Get result failed: ${resultResponse.data.msg}`);

 }

 console.log("获取结果");

 console.log(resultResponse.data);

 const text = resultResponse.data.result.map((item) => item.sentence).join("\n");

 fs.writeFileSync(fileName, text);

}


// 生成 UUID v4

function uuidv4() {

 return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {

   var r = (Math.random() * 16) | 0,

     v = c == "x" ? r : (r & 0x3) | 0x8;

   return v.toString(16);

 });

}


网易与微软对比

微软

网易

获取结果需要轮询

不需要

需要

准确度

略高

略低

接口方便程度

一个订阅模式, 每秒钟都会给你返回信息, 直到任务完成,

感觉比网易方便一些

四个步骤: 准备, 上传, 获取状态, 获取结果

需要mp3转wav

需要

不需要

建议用哪个

都可以, 都差不多

写代码利器

本文的代码大部分是 ChatGPT4 写的,

你如果不想动手, 可以像我一样, 直接复制黏贴网易有道云的文档, 然后叫chatgpt给你代码

就像这样

我用的 ChatGPT4, 是这个

ChatGPT联网版, Stable Diffusion画图, 这个星球全都有, 低调使用, 别外传

声明

本文仅供学习研究使用, 禁止用于其他用途


微信公众号 牙叔教程


相关实践学习
达摩院智能语音交互 - 声纹识别技术
声纹识别是基于每个发音人的发音器官构造不同,识别当前发音人的身份。按照任务具体分为两种: 声纹辨认:从说话人集合中判别出测试语音所属的说话人,为多选一的问题 声纹确认:判断测试语音是否由目标说话人所说,是二选一的问题(是或者不是) 按照应用具体分为两种: 文本相关:要求使用者重复指定的话语,通常包含与训练信息相同的文本(精度较高,适合当前应用模式) 文本无关:对使用者发音内容和语言没有要求,受信道环境影响比较大,精度不高 本课程主要介绍声纹识别的原型技术、系统架构及应用案例等。 讲师介绍: 郑斯奇,达摩院算法专家,毕业于美国哈佛大学,研究方向包括声纹识别、性别、年龄、语种识别等。致力于推动端侧声纹与个性化技术的研究和大规模应用。
相关文章
|
NoSQL Redis
Mac安装Redis(图文解说详细版)
Mac安装Redis(图文解说详细版)
Mac安装Redis(图文解说详细版)
|
人工智能 搜索推荐 API
蚂蚁百宝箱联手深铁打造全国首个地铁 AI 智能体「深铁宝」:你的全能城市向导来啦~
蚂蚁百宝箱联合深铁集团、深圳通推出全国首个“公共出行+城市服务”AI智能体「深铁宝」,上线于深圳地铁、深圳通及支付宝APP,实现一句话直达、秒级响应的智慧出行体验,涵盖出行规划、乘车码快捷调取、周边生活服务推荐等一站式功能,助力城市交通与服务数字化升级。
937 0
蚂蚁百宝箱联手深铁打造全国首个地铁 AI 智能体「深铁宝」:你的全能城市向导来啦~
|
6月前
|
存储 缓存 安全
《第一次启动QClaw,这5个设置决定你未来半年的使用上限》
本文针对多数用户首次启动QClaw直接使用、导致长期体验不佳的普遍误区,指出QClaw作为可进化智能体,首次初始化设置直接决定其未来半年的使用上限。文章基于实际使用经验,深度拆解了必须完成的5项核心基础设置:分层配置系统权限、按任务类型定制模型路由与优先级、开启微信指令白名单安全隔离、选择性启用技能包并优化缓存、迁移本地数据存储并配置P2P多端同步。文章纠正了默认设置的常见问题,帮助用户避免后期改配置的高成本,充分释放QClaw的执行效率与潜力。
1281 3
《第一次启动QClaw,这5个设置决定你未来半年的使用上限》
|
7月前
|
编解码 物联网 数据处理
LTX-2.3开源: 视频生成引擎级升级
Lightricks开源LTX-2.3音视频大模型:重建VAE提升细节锐度,文本连接器扩容4倍增强Prompt遵循,大幅优化I2V运动自然性与音频质量,并首次原生支持1080×1920竖版视频生成。22B参数,支持文生视频、图生视频等多任务。
6320 4
|
负载均衡 并行计算 异构计算
大模型训练推理优化(5): FlexLink —— NVLink 带宽无损提升27%
本期我们将介绍蚂蚁集团ASystem团队在大模型通信优化上的新工作FlexLink,旨在通过动态聚合多路通信(NVLink,PCIe,RDMA),在H800等典型硬件上将典型通信算子如(AllReduce, All Gather)吞吐提升最高达27%,尤其适合大模型长序列推理(Prefill阶段),及训练等通信密集的带宽bound场景。方案对精度无影响。
|
7月前
|
运维 数据可视化 机器人
OpenClaw Dashboard多智能体可视化管理方案:零配置面板+阿里云/本地全系统部署+模型配置完整版
在多智能体成为AI应用标配的2026年,个人与小团队普遍面临同一困境:同时运行多个OpenClaw Agent对接不同通讯平台,却缺乏统一管控入口——机器人在线状态、模型可用性、Token消耗、会话负载、服务异常全靠手动排查,管理成本随Agent数量呈指数级上升。OpenClawDashboard的出现,以**零配置、无数据库、轻量运行、实时读取**的设计理念,彻底解决多智能体运维混乱问题,将原本繁琐的人工巡检转化为可视化、一站式、可告警的高效管理模式。
2000 1
|
7月前
|
人工智能 Linux API
零基础用OpenClaw实现公众号AI自动发文:阿里云/本地部署+Skill配置+避坑大全,效率提升90%
2026年,AI驱动内容自动化已经成为自媒体与企业运营的标配,而OpenClaw(Clawdbot)凭借极强的插件扩展能力、本地可控、全平台部署的优势,成为公众号自动发文、智能写稿、一键排版的最强工具。通过一套完整的Skill插件,用户只需要一句指令,就能让AI完成选题、写作、配图、排版、上传图片、生成草稿、推送预览的全流程,将原本2小时的工作压缩到10分钟以内,效率提升90%以上。
2366 7
|
10月前
|
消息中间件 人工智能 NoSQL
RocketMQ:A2A协议实现多智能体优化
Apache RocketMQ推出LiteTopic轻量级通信模型,结合A2A协议与AgentScope框架,为多智能体系统提供高可靠、低延迟的异步通信方案,支持会话持久化、断点续传与动态协同,助力AI应用构建稳定高效的协作基座。
 RocketMQ:A2A协议实现多智能体优化
|
SQL 存储 Oracle
19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍|学习笔记
快速学习19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍
19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍|学习笔记
|
缓存 Java 数据库连接
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
647 4

热门文章

最新文章