This commit is contained in:
2025-04-30 18:53:45 +08:00
parent b07bcc5454
commit 4a2d3e8d32
12 changed files with 171 additions and 53 deletions

View File

@@ -1,7 +1,7 @@
import { BaseChat, BaseChatOptions } from '../core/chat.ts';
import { OpenAI } from 'openai';
type SiliconFlowOptions = Partial<BaseChatOptions>;
export type SiliconFlowOptions = Partial<BaseChatOptions>;
type SiliconFlowUsageData = {
id: string;

View File

@@ -107,4 +107,11 @@ export class BaseChat implements BaseChatInterface, BaseChatUsageInterface {
completion_tokens: this.completion_tokens,
};
}
getHeaders(headers?: Record<string, string>) {
return {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.apiKey}`,
...headers,
};
}
}

View File

@@ -0,0 +1 @@
export * from './video/siliconflow.ts';

View File

@@ -0,0 +1,37 @@
import { SiliconFlow } from './../../chat-adapter/siliconflow.ts';
export class VideoSiliconFlow extends SiliconFlow {
constructor(opts: any) {
super(opts);
}
async uploadAudioVoice(audioBase64: string | Blob | File) {
const pathname = 'uploads/audio/voice';
const url = `${this.baseURL}/${pathname}`;
const headers = {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${this.apiKey}`,
};
const formData = new FormData();
// formData.append('audio', 'data:audio/mpeg;base64,aGVsbG93b3JsZA==');
// formData.append('audio', audioBase64);
formData.append('file', audioBase64);
formData.append('model', 'FunAudioLLM/CosyVoice2-0.5B');
formData.append('customName', 'test_name');
formData.append('text', '在一无所知中, 梦里的一天结束了,一个新的轮回便会开始');
const res = await fetch(url, {
method: 'POST',
headers,
body: formData,
}).then((res) => res.json());
console.log('uploadAudioVoice', res);
}
async audioSpeech() {
this.openai.audio.speech.create({
model: 'FunAudioLLM/CosyVoice2-0.5B',
voice: 'alloy',
input: '在一无所知中, 梦里的一天结束了,一个新的轮回便会开始',
response_format: 'mp3',
});
}
}

View File

@@ -0,0 +1,100 @@
import { SiliconFlow } from '../../../provider/chat-adapter/siliconflow.ts';
import { VideoSiliconFlow } from '../../../provider/media/video/siliconflow.ts';
import dotenv from 'dotenv';
import fs from 'fs';
import path from 'path';
import Stream from 'stream';
dotenv.config();
const siliconflow = new SiliconFlow({
apiKey: process.env.SILICONFLOW_API_KEY,
model: 'Qwen/Qwen2-7B-Instruct',
});
const videoSiliconflow = new VideoSiliconFlow({
apiKey: process.env.SILICONFLOW_API_KEY,
model: 'Qwen/Qwen2-7B-Instruct',
});
const main = async () => {
const usage = await siliconflow.getUsageInfo();
console.log(usage);
};
// main();
const mainChat = async () => {
const test2=`我永远记得那个改变一切的下午。十八岁生日后的第三天,我正坐在自家后院的老橡树杈上,用平板电脑调试我最新设计的森林动物追踪程序。我的红发——妈妈总说像"燃烧的枫叶"——在午后的阳光下泛着铜色的光泽,有几缕不听话的发丝被微风拂过我的脸颊。
"芮薇!"妈妈的声音从厨房窗口传来,"外婆发来加密信息,说需要你马上过去一趟。"
我差点从树上掉下来。外婆从不发加密信息——除非情况紧急。作为退休的网络安全专家,外婆一直教导我"过度谨慎总比后悔莫及"。`
try {
const res = await siliconflow.openai.audio.speech.create({
model: 'FunAudioLLM/CosyVoice2-0.5B',
// voice: 'FunAudioLLM/CosyVoice2-0.5B:diana',
voice: 'speech:test:h36jngt7ms:zarwclhblfjfyonslejr',
// input: '在一无所知中, 梦里的一天结束了,一个新的轮回便会开始',
// input: '这是一个新的轮回,非常有趣的故事。',
input: test2,
response_format: 'mp3',
});
console.log(res);
const dir = path.join(process.cwd(), 'videos');
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
const filePath = path.join(dir, `output-${Date.now()}.mp3`);
// 假设 res 是一个可读流
if (res instanceof Stream.Readable) {
const writeStream = fs.createWriteStream(filePath);
res.pipe(writeStream);
return new Promise((resolve, reject) => {
writeStream.on('finish', () => {
console.log('文件已保存至:', filePath);
resolve(filePath);
});
writeStream.on('error', reject);
});
}
// 假设 res 是一个 ArrayBuffer 或 Buffer
else if (res.arrayBuffer) {
const buffer = Buffer.from(await res.arrayBuffer());
fs.writeFileSync(filePath, buffer);
console.log('文件已保存至:', filePath);
return filePath;
}
// 假设 res 是一个包含 blob 的对象
else if (res.blob) {
// @ts-ignore
const buffer = Buffer.from(res.blob, 'base64');
fs.writeFileSync(filePath, buffer);
console.log('文件已保存至:', filePath);
return filePath;
} else {
throw new Error('无法识别的响应格式');
}
} catch (error) {
console.error('保存音频文件时出错:', error);
throw error;
}
};
mainChat();
const vidioUpload = async () => {
const filePath = path.join(process.cwd(), 'videos', 'my_speech_text.mp3');
const fileBuffer = fs.readFileSync(filePath);
const fileBase64 = 'data:audio/mpeg;base64,' + fileBuffer.toString('base64');
console.log('fileBase64', fileBase64.slice(0, 100));
const fileBlob = new Blob([fileBuffer], { type: 'audio/wav' });
const file = new File([fileBlob], 'my_speech_text.mp3', { type: 'audio/mp3' });
const res = await videoSiliconflow.uploadAudioVoice(file);
// console.log('vidioUpload', res);
// uri:speech:test:h36jngt7ms:zarwclhblfjfyonslejr
return res;
};
// vidioUpload();