Commit 163f7c92 by haojie

音频切割交给python

parent 81203f07
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
"lint:fix": "eslint --ext .vue,.js,jsx,.ts,.tsx ./ --max-warnings 0 --fix", "lint:fix": "eslint --ext .vue,.js,jsx,.ts,.tsx ./ --max-warnings 0 --fix",
"stylelint": "stylelint src/**/*.{html,vue,sass,less}", "stylelint": "stylelint src/**/*.{html,vue,sass,less}",
"stylelint:fix": "stylelint --fix src/**/*.{html,vue,vss,sass,less}", "stylelint:fix": "stylelint --fix src/**/*.{html,vue,vss,sass,less}",
"prepare": "husky install",
"site:preview": "npm run build && cp -r dist _site", "site:preview": "npm run build && cp -r dist _site",
"test": "echo \"no test specified,work in process\"" "test": "echo \"no test specified,work in process\""
}, },
...@@ -21,7 +20,6 @@ ...@@ -21,7 +20,6 @@
"dayjs": "^1.10.6", "dayjs": "^1.10.6",
"default-passive-events": "^2.0.0", "default-passive-events": "^2.0.0",
"js-cookie": "^3.0.1", "js-cookie": "^3.0.1",
"lamejs": "^1.2.1",
"tdesign-vue-next": "^0.22.1", "tdesign-vue-next": "^0.22.1",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"vue": "^3.2.31", "vue": "^3.2.31",
...@@ -34,8 +32,8 @@ ...@@ -34,8 +32,8 @@
"@typescript-eslint/eslint-plugin": "^6.2.0", "@typescript-eslint/eslint-plugin": "^6.2.0",
"@typescript-eslint/parser": "^6.2.0", "@typescript-eslint/parser": "^6.2.0",
"@vitejs/plugin-legacy": "^4.1.0", "@vitejs/plugin-legacy": "^4.1.0",
"@vitejs/plugin-vue": "^1.3.0", "@vitejs/plugin-vue": "^4.2.3",
"@vitejs/plugin-vue-jsx": "^1.1.7", "@vitejs/plugin-vue-jsx": "^3.0.1",
"axios": "^0.24.0", "axios": "^0.24.0",
"eslint": "^8.45.0", "eslint": "^8.45.0",
"eslint-plugin-vue": "^9.15.1", "eslint-plugin-vue": "^9.15.1",
......
...@@ -132,3 +132,6 @@ export const createLiveRouteKey = 'create_live_route_key'; ...@@ -132,3 +132,6 @@ export const createLiveRouteKey = 'create_live_route_key';
// 音频上传格式限制 // 音频上传格式限制
export const audioAccept = 'wav'; export const audioAccept = 'wav';
// 音频切割间隔时长
export const audioSplitDuration = 300;
...@@ -479,7 +479,7 @@ const audioSplit = async () => { ...@@ -479,7 +479,7 @@ const audioSplit = async () => {
let fileDuration = await getDurationOfAudioFile(row.file.raw); let fileDuration = await getDurationOfAudioFile(row.file.raw);
console.log(fileDuration, '文件时长'); console.log(fileDuration, '文件时长');
if (fileDuration > audioSplitNum) { if (fileDuration > audioSplitNum) {
// 开始切割 // 开始切割前先判断文件类型
let result = await splitAudio(row.file.raw, audioSplitNum); let result = await splitAudio(row.file.raw, audioSplitNum);
if (result.length) { if (result.length) {
// 上传阿里云 // 上传阿里云
......
...@@ -81,9 +81,10 @@ import { getDigitalPeopleList, uploadToAly } from '@/service/Common'; ...@@ -81,9 +81,10 @@ import { getDigitalPeopleList, uploadToAly } from '@/service/Common';
import Button from '@/components/Button.vue'; import Button from '@/components/Button.vue';
import { callPyjsInWindow, injectWindow } from '@/utils/pyqt'; import { callPyjsInWindow, injectWindow } from '@/utils/pyqt';
import { jumpToCreateLivePage } from '@/router/jump'; import { jumpToCreateLivePage } from '@/router/jump';
import { audioMerge, downloadAudioList } from '@/utils/audio'; import { audioMerge, downloadAudioList, splitAudio } from '@/utils/audio';
import { randomIntFormList } from '@/utils/tool'; import { getFile, randomIntFormList } from '@/utils/tool';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { audioSplitDuration } from '@/constants/token';
const router = useRouter(); const router = useRouter();
const store = useStore(); const store = useStore();
...@@ -204,27 +205,28 @@ const startTest = async () => { ...@@ -204,27 +205,28 @@ const startTest = async () => {
// 'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ad08fa0a70ae4ea88d11ad5e394ce045.wav?Expires=1692149777&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=D93qMT1DovslSOVa9oufV2cGZxE%3D', // 'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ad08fa0a70ae4ea88d11ad5e394ce045.wav?Expires=1692149777&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=D93qMT1DovslSOVa9oufV2cGZxE%3D',
// 'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ad08fa0a70ae4ea88d11ad5e394ce045.wav?Expires=1692149777&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=D93qMT1DovslSOVa9oufV2cGZxE%3D', // 'http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/ad08fa0a70ae4ea88d11ad5e394ce045.wav?Expires=1692149777&OSSAccessKeyId=LTAIUpwNp2H7pBG5&Signature=D93qMT1DovslSOVa9oufV2cGZxE%3D',
// ]; // ];
// let blob = await audioMerge(list); let list = [
// console.log(blob); 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11dd2372d8-73ff-4526-bf59-b1618a3f218f.mp3',
// if (blob) { ];
// // uploadToAly([blob]); // 注入一个接收方法
// } else { const splitCallback = (url: string[]) => {
// console.log('文件错误'); console.log(url, '切割后的音频列表');
// } };
// let list = [ injectWindow('splitAudioCallback', splitCallback);
// 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-114e482462-6047-47be-a30c-b85a17c95665.mp3', // 传给python
// 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11efe3f1ea-b445-42e2-93b0-39a70fb7c6f5.mp3', console.log('通知切割');
// 'http://yunyi-live.oss-cn-hangzhou.aliyuncs.com/upload/1/2023-08-11dd2372d8-73ff-4526-bf59-b1618a3f218f.mp3', callPyjsInWindow('splitAudio', {
// ]; url: list[0],
// const { blobList } = await downloadAudioList(list); duration: audioSplitDuration,
// console.log(blobList, '下载完毕,传给python'); id: 1,
// callPyjsInWindow('mergeAudio', blobList, false, 0, false); });
}; };
onMounted(() => { onMounted(() => {
// 获取我的数字人 // 获取我的数字人
getList(); getList();
startTest(); startTest();
// 发送token,即使重新登录也会回到首页再次发送
callPyjsInWindow('setToken', userToken.value); callPyjsInWindow('setToken', userToken.value);
}); });
</script> </script>
......
...@@ -12,6 +12,7 @@ import { LIVE_AUDIT_STATUS } from './Live'; ...@@ -12,6 +12,7 @@ import { LIVE_AUDIT_STATUS } from './Live';
import { audioMerge, splitAudio } from '@/utils/audio'; import { audioMerge, splitAudio } from '@/utils/audio';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { writeLog } from '@/utils/pyqt'; import { writeLog } from '@/utils/pyqt';
import { audioSplitDuration } from '@/constants/token';
// 阿里云上传配置 // 阿里云上传配置
export const getUploadConfig = async () => { export const getUploadConfig = async () => {
...@@ -148,7 +149,7 @@ export const audioStart = async (list: any[], dimensional: boolean = true) => { ...@@ -148,7 +149,7 @@ export const audioStart = async (list: any[], dimensional: boolean = true) => {
let file = await audioMerge(list); let file = await audioMerge(list);
if (file) { if (file) {
// 开始切割 // 开始切割
let split_list = await splitAudio(file, 300); let split_list = await splitAudio(file, audioSplitDuration);
// 合并后的文件上传 // 合并后的文件上传
if (split_list && split_list.length) { if (split_list && split_list.length) {
let result = await uploadToAly(split_list); let result = await uploadToAly(split_list);
......
import audiobufferToWav from 'audiobuffer-to-wav'; import audiobufferToWav from 'audiobuffer-to-wav';
import { callPyjsInWindow, writeLog } from '@/utils/pyqt'; import { callPyjsInWindow, writeLog } from '@/utils/pyqt';
// import lamejs from 'lamejs';
import { getFile } from './tool'; import { getFile } from './tool';
import audioConversion from '@/worker/audioConversion.js?worker';
// import lamejs from 'lamejs';
// import audioConversion from '@/worker/audioConversion.js?worker';
// dev
// "@vitejs/plugin-vue": "^1.3.0",
// "@vitejs/plugin-vue-jsx": "^1.1.7",
export const createAudioContext = () => { export const createAudioContext = () => {
return new (window.AudioContext || window.webkitAudioContext)(); return new (window.AudioContext || window.webkitAudioContext)();
...@@ -40,11 +45,13 @@ export const getDurationOfAudioFile = (file: File | string) => { ...@@ -40,11 +45,13 @@ export const getDurationOfAudioFile = (file: File | string) => {
}); });
}; };
// 获取音频文件的类型 // 获取音频文件的类型(后缀名)
export const getAudioFileType = async (url: string) => { export const getAudioFileType = async (url: string | Blob) => {
if (typeof url === 'string') {
const audio = await getFile(url); const audio = await getFile(url);
let type = audio.type; let type = audio.type;
return type; return type;
}
}; };
// 将blob音频列表转换为buffer // 将blob音频列表转换为buffer
...@@ -104,23 +111,23 @@ function mergeBuffers(bufferList) { ...@@ -104,23 +111,23 @@ function mergeBuffers(bufferList) {
} }
// mp3 worker // mp3 worker
export const mp3Worker = async (blobList: any[]) => { // export const mp3Worker = async (blobList: any[]) => {
return new Promise<Blob>((reslove) => { // return new Promise<Blob>((reslove) => {
// worker // // worker
const worker: Worker = new audioConversion(); // const worker: Worker = new audioConversion();
worker.onmessage = function (event) { // worker.onmessage = function (event) {
const blob = event.data; // const blob = event.data;
// 结束线程 // // 结束线程
worker.terminate(); // worker.terminate();
// 处理编码后的数据,例如保存为文件或进行其他操作 // // 处理编码后的数据,例如保存为文件或进行其他操作
reslove(blob); // reslove(blob);
}; // };
console.log('发送消息'); // console.log('发送消息');
worker.postMessage({ // worker.postMessage({
blobList: blobList, // blobList: blobList,
}); // });
}); // });
}; // };
// 导出为 MP3 // 导出为 MP3
// export function exportToMp3(bufferList) { // export function exportToMp3(bufferList) {
...@@ -217,7 +224,7 @@ export async function audioMerge(filePaths: string[]) { ...@@ -217,7 +224,7 @@ export async function audioMerge(filePaths: string[]) {
// const blob = await mp3Worker(blobList); // const blob = await mp3Worker(blobList);
// return blob; // return blob;
// 通知python处理 // 通知python处理
await pyAudioMerge(blobList); // await pyAudioMerge(blobList);
} }
} catch (error) { } catch (error) {
writeLog({ writeLog({
...@@ -228,7 +235,9 @@ export async function audioMerge(filePaths: string[]) { ...@@ -228,7 +235,9 @@ export async function audioMerge(filePaths: string[]) {
} }
} }
export const splitAudio = async (audioBlob: Blob, duration: number) => { // 切割wav格式的音频
export const splitWavAudio = async (audioBlob: Blob, duration: number) => {
console.log('开始切割wav');
const audioContext = new AudioContext(); const audioContext = new AudioContext();
const audioBufferList = []; const audioBufferList = [];
...@@ -261,16 +270,25 @@ export const splitAudio = async (audioBlob: Blob, duration: number) => { ...@@ -261,16 +270,25 @@ export const splitAudio = async (audioBlob: Blob, duration: number) => {
const sourceData = audioBuffer.getChannelData(channel).subarray(startFrame, endFrame); const sourceData = audioBuffer.getChannelData(channel).subarray(startFrame, endFrame);
slicedBuffer.copyToChannel(sourceData, channel); slicedBuffer.copyToChannel(sourceData, channel);
} }
// 将切割后的音频 Buffer 添加到列表中 // 将切割后的音频 Buffer 添加到列表中
const wavData = audiobufferToWav(slicedBuffer); const wavData = audiobufferToWav(slicedBuffer);
const blob = new Blob([wavData], { type: 'audio/wav' }); const blob = new Blob([wavData], { type: audioBlob.type });
audioBufferList.push(blob); audioBufferList.push(blob);
} }
return audioBufferList; return audioBufferList;
}; };
export const splitAudio = async (audioBlob: Blob, duration: number) => {
const start = performance.now();
let list = [];
// wav
list = await splitWavAudio(audioBlob, duration);
const end = performance.now();
console.log(`本次切割共耗费:${parseInt((end - start) / 1000 + '')}秒`);
return list;
};
// 导出音频缓冲区为 WAV 文件 // 导出音频缓冲区为 WAV 文件
function exportBufferAsWav(audioBuffer) { function exportBufferAsWav(audioBuffer) {
const numberOfChannels = audioBuffer.numberOfChannels; const numberOfChannels = audioBuffer.numberOfChannels;
......
...@@ -31,6 +31,10 @@ export const callPyjsInWindow = ( ...@@ -31,6 +31,10 @@ export const callPyjsInWindow = (
timeout: number = 1000, timeout: number = 1000,
toJson: boolean = true, toJson: boolean = true,
) => { ) => {
if (!window.pyjs) {
console.log('py没有注入');
return;
}
try { try {
const getValue = () => { const getValue = () => {
if (toJson) { if (toJson) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment