Я строю интерфейс чата на Wix, используя пользовательский веб -компонент и iframe для пользовательского интерфейса Chat. Идея:
- Пользователь нажимает «Запись» в Iframe → «Сообщение, отправленное на родительскую страницу» (поскольку Wix не позволяет iframe делать запись)
- родительская страница говорит/остановить запись через атрибут Action
Запустить/остановить записи через атрибут
Запустить/остановить записи через атрибут
. /> Регистратор захватывает аудио webm < /p>
< /li>
преобразование в mp3 с lamejs и обнажает base64 data-url < /p>
< /li>
Нажмите «Загрузка» в рекордере. /> < /li>
< /ol>
(я загружаю mp3 в CMS только для получения публичного URL; это на самом деле не требуется для хранения, это просто для создания URL. Эта попытка также не сработала) < /p>
parentia preation upplaintiaRudiOfrom Whisper API) - транскрипт вводится обратно в ввод в чате и отправляется в чат
Frontend Suldier в коде страницы Wix < /li>
< /ol>
Код: Выделить всё
// in $w.onReady(...)
globalThis.addEventListener("message", async (event) => {
const { type, audio } = event.data || {};
if (type === "audioMessage" && audio) {
try {
// 1) Upload Base64 → Wix Media (only to get a public URL)
const fileUrl = await uploadAudioFromBase64(audio);
const publicUrl = await getDownloadUrl(fileUrl);
// 2) Show user audio in chat
$w("#chatFrame").postMessage({ name: "User", audio: publicUrl });
// 3) Transcribe via Whisper
const transcript = await transcribeAudioFromUrl(publicUrl);
// 4) Inject transcript and ask AI
$w("#chatFrame").postMessage({ type: "setInputField", text: transcript });
const reply = await getAnswerFromAI(transcript);
$w("#chatFrame").postMessage({ name: "OpenAI", text: reply });
} catch (err) {
console.error("Upload or transcription error:", err);
$w("#chatFrame").postMessage({
name: "OpenAI",
text: "❌"
});
}
}
});
< /code>
wix Backend < /li>
< /ol>
import { webMethod, Permissions } from 'wix-web-module';
import { getSecret } from 'wix-secrets-backend';
import axios from 'axios';
const FormData = require('form-data');
// Helper: convert wix:document URL → public HTTPS URL
async function ensurePublicUrl(url) {
if (/^wix:document:\/\//.test(url)) {
return await mediaManager.getDownloadUrl(url);
}
return url;
}
// Send binary buffer → Whisper API
async function whisperTranscription(buffer, mimeType) {
const apiKey = await getSecret('OPENAI-API-KEY');
const form = new FormData();
form.append('file', buffer, { filename: 'recording', contentType: mimeType });
form.append('model', 'whisper-1');
form.append('response_format', 'text');
const { data } = await axios.post(
'https://api.openai.com/v1/audio/transcriptions',
form,
{ headers: { ...form.getHeaders(), Authorization: `Bearer ${apiKey}` } }
);
return data;
}
export const transcribeAudioFromUrl = webMethod(Permissions.Anyone, async (url) => {
const publicUrl = await ensurePublicUrl(url);
const res = await axios.get(publicUrl, { responseType: 'arraybuffer' });
return whisperTranscription(Buffer.from(res.data), 'audio/mp3');
});
< /code>
Костюм -элемент регистрации < /li>
< /ol>
async handleStop() {
const blob = new Blob(this.audioChunks, { type: 'audio/webm' });
const arrayBuffer = await blob.arrayBuffer();
const mp3Blob = await this.convertToMp3(arrayBuffer);
this.lastMp3Blob = mp3Blob;
// show preview + enable upload…
this.uploadBtn.disabled = false;
}
uploadRecording() {
if (!this.lastMp3Blob) return;
const reader = new FileReader();
reader.onloadend = () => {
const base64 = reader.result;
window.parent.postMessage({ type: 'audioMessage', audio: base64 }, '*');
this.uploadBtn.textContent = '✅ Uploaded!';
this.uploadBtn.disabled = true;
};
reader.readAsDataURL(this.lastMp3Blob);
}
// … convertToMp3() & floatTo16BitPCM() using lamejs …
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... nscription