π― 100% μ ν νμμ€ν¬ν SRT!
π€ μ₯λ©΄λ³ TTS β μ€μ νμμ€ν¬ν β μλ²½ν μλ§
Inworld AI Word-Level Timestamps + WAV λ³ν©
β οΈ Cloudflare Worker νμ!
λ€μ΄λ‘λλ₯Ό μν΄ Worker URL μ€μ νμ
π― V24.1 ν΅μ¬ - 100% μ ν νμμ€ν¬ν!
- β μ₯λ©΄λ³ κ°λ³ TTS: κ° μ₯λ©΄μ λ°λ‘ μμ±νμ¬ μ νν μκ° μΈ‘μ
- β Word-Level Timestamps: Inworld APIκ° μ 곡νλ μ€μ λ¨μ΄λ³ μκ°
- β 100% λκΈ°ν: μΆμ μ΄ μλ μ€μ μ€λμ€ κΈΈμ΄ κΈ°λ°!
- β 볡μ μμ± μ§μ: 컀μ€ν Voice IDλ‘ λλ§μ μμ± μ¬μ© κ°λ₯
π€ TTS ν€ (Inworld AI) TIMESTAMPS!
λ¨μ΄ λ 벨 νμμ€ν¬ν μ§μ TTS + μμ± λ³΅μ
λ°κΈ ββοΈ Cloudflare Workers λ¬΄λ£ νμ!
λ€μ΄λ‘λ CORS ν΄κ²°
export default {
async fetch(request) {
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
};
if (request.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
const url = new URL(request.url);
const targetUrl = url.searchParams.get('url');
if (!targetUrl) {
return new Response('Missing url', { status: 400, headers: corsHeaders });
}
try {
const response = await fetch(decodeURIComponent(targetUrl));
const responseHeaders = new Headers(response.headers);
Object.entries(corsHeaders).forEach(([k, v]) => responseHeaders.set(k, v));
return new Response(response.body, { status: response.status, headers: responseHeaders });
} catch (e) {
return new Response(e.message, { status: 500, headers: corsHeaders });
}
}
};
π API & μΊλ¦ν° μ€μ
β οΈ μΊλ¦ν° μ΄λ―Έμ§ μ λ‘λ
π Gem κ²°κ³Ό λΆμ¬λ£κΈ°
π λλ³Έ
π― V24.1: μ€μ νμμ€ν¬ν κΈ°λ°!
β
κ° μ₯λ©΄ λμ¬λ₯Ό κ°λ³ TTS μμ±
β
Inworld API timestamp_type: "WORD" μ¬μ©
β
μ€μ μ€λμ€ κΈΈμ΄λ‘ 100% μ νν SRT μλ μμ±