Changelog
Thay đổi của Cloud API (/api/v1). Mọi mục đánh dấu ⚠️ Thay đổi hành vi đều
có thể ảnh hưởng đến tích hợp đang chạy của bạn, kể cả khi bạn không sửa gì.
2026-10-10 — Gói của key không trả được thì các gói khác của bạn trả
⚠️ Thay đổi hành vi
Request mà gói của key không trả được thì một gói khác của bạn trả. Mỗi key tính tiền trên một gói. Trước đây, khi gói đó không trả được — còn quá ít token, chạm hạn mức ngày hoặc tuần, hết hạn — request bị từ chối, kể cả khi tài khoản còn một gói khác đang hoạt động và dư dả: gói còn 99 token không bao giờ trả nổi 195 token của một request V4, nên nó không bao giờ "hết", và mọi lời gọi đều bị từ chối ngay cạnh một gói quà 400.000 token. Giờ gói của key vẫn trả trước mỗi khi trả được; khi không, gói cũ nhất trong số các gói còn hoạt động khác của bạn có hỗ trợ engine đó sẽ trả, đúng như trong web app. Mỗi request vẫn do một gói trả, và tiền hoàn luôn về đúng gói đã trả. Không có gì rơi xuống phần miễn phí hằng ngày. Sách nói và MCP server tính tiền theo cùng cách này.
GET /v1/balance theo cùng quy tắc. remaining là chỗ trống nhiều nhất của
một gói trả được (không bao giờ là tổng), và plan là gói mà con số đó đo trên —
không còn luôn là gói của key.
Key có gói không còn hoạt động giờ nhận được code. Khi gói mà key gắn vào đã
dùng hết, hết hạn hoặc đã được thay, và không gói nào khác đang hoạt động trả được,
lỗi 403 giờ kèm code: "GRANT_INACTIVE" và required. Trước đây chỉ có câu chữ,
không có code. Xem Lỗi.
Bắt đầu sách nói tính mọi gói trả được, theo từng chương.
POST /v1/audiobooks/{bookId}/start trước đây chỉ so cuốn sách với gói của key.
Mỗi chương do một gói trả trọn, nên giờ nó trả 402 insufficient_tokens khi các
gói của bạn cộng lại không đủ cho các chương, hoặc khi có chương tới lượt mà không
gói nào trả được — ví dụ hai chương 39.000 token trên ba gói mỗi gói 30.000. Lỗi
thứ hai nêu tên chương đó, kèm ước tính của chương là required và số nhiều nhất
một gói còn lại lúc đó là remaining.
Mới
spendableTokens trong GET /v1/balance. Tổng số key tiêu được ngay lúc này,
request này nối request kia: mọi gói trả được, mỗi gói tính tới hạn mức ngày và
tuần của riêng nó, cộng lại. Con số giảm đúng bằng chi phí mỗi request, dù gói nào
trả — remaining thì không còn như vậy khi gói của key trả cạnh một gói lớn hơn.
Chỉ một gói thì nó bằng remaining. MCP server hiện con số này sau mỗi lần tạo
audio.
plan.isGift trong GET /v1/balance. plan là gói còn nhiều chỗ nhất, nên
nó có thể là token VieNeu tặng chứ không phải một gói: gói còn 99 token cạnh
400.000 token được tặng thì plan là phần được tặng. isGift: true cho biết điều
đó — token tặng không có hạn mức ngày/tuần và không hết hạn — để client không gọi
nó là gói bạn đang dùng. MCP server giờ gọi đúng là token được tặng.
2026-10-02 — Sách nói dài: không mất chữ, không kẹt
⚠️ Thay đổi hành vi
Chương dài hơn mức gói tạo được bị từ chối ngay lúc thêm. Mỗi chương được
tính tiền trong một lần, nên với gói có hạn mức token theo ngày hoặc tuần, chương
tốn nhiều hơn hạn mức không bao giờ bắt đầu được: trước đây nó nằm chờ token mãi.
Giờ POST /v1/audiobooks/{bookId}/chapters trả 400 chapter_over_plan_limit kèm
chapterCharsMax, và mọi cuốn sách đều báo chapterCharsMax. Gói không có hạn mức
như vậy thì giữ nguyên (60.000 ký tự).
Mới
afterSegment khi nối tiếp một chương. Đi cùng appendTo, truyền số đoạn
chương đang có; số khác đi thì nhận 409 segment_mismatch kèm câu chương đang kết
thúc, nên request gửi lại không thêm chữ hai lần và request bị mất không để lại lỗ
hổng. Không truyền thì request lặp đúng các đoạn cuối của chương nhận 409
duplicate_segments, còn chương mới giống hệt chương vừa thêm nhận 409
duplicate_chapter. Công cụ MCP add_audiobook_chapter nhận after_segment và
cho thấy mỗi chương hiện kết thúc thế nào. Xem
Sách nói.
Thay đổi
Chương lỗi tự được tạo lại. Chương có job lỗi — deploy thay máy chủ hai lần trong lúc tạo một chương dài, máy chủ giọng gặp sự cố — vẫn được hoàn token như trước, rồi tự tạo lại sau vài phút, tối đa hai lần, dùng tiếp các phần đã xong. Job đứng yên 45 phút cũng bị đánh lỗi và hoàn token như vậy, nên không còn chặn mọi sách khác. Bước hoàn thiện MP3 thử lại với thời gian chờ tăng dần trong khoảng một giờ rồi mới giao WAV, và bản thu tải về bị thiếu, hay MP3 ngắn hơn bản thu, bị từ chối chứ không được giao.
Đỉnh của MP3 nằm dưới −3 dBTP. Bước hoàn thiện giờ đặt mục tiêu thấp hơn nửa decibel và thêm bộ giới hạn đỉnh trước khi nén MP3, vì bước nén làm đỉnh nhích lên một chút: hai chương của một cuốn sách thử trên prod đã chạm −2,8 dBTP. Độ lớn vẫn giữ ở −19 LUFS.
2026-10-01 — Sách nói, qua API và trong MCP server
Mới
Sách nói. Một cuốn sách gồm một giọng dẫn chuyện và tối đa 30 giọng nhân vật
đọc các chương viết dưới dạng kịch bản — lời dẫn chuyện, và từng câu thoại kèm
nhân vật nói câu đó. POST /v1/audiobooks tạo sách,
POST /v1/audiobooks/{bookId}/chapters thêm chương, POST /v1/audiobooks/{bookId}/start
đưa vào hàng chờ, GET /v1/audiobooks/{bookId} theo dõi tiến độ kèm link tải của
từng chương đã xong. Sách được tạo ở chế độ nền, mỗi lần một chương, vào lúc cụm
GPU rảnh, nên mất cỡ vài giờ chứ không phải vài giây. Mỗi chương bị trừ token theo
ký tự khi bắt đầu tạo, được hoàn nếu lỗi, được xử lý âm thanh thành MP3 (−19 LUFS,
đỉnh ≤ −3 dBTP, khoảng lặng hai đầu, thẻ ID3) và lưu vào Thư viện. Chỉ key LIVE và
giọng trong kho. Xem Toàn bộ operation.
Sách nói trong MCP server. Sáu công cụ và một trình phát chương giúp Claude hoặc ChatGPT biến văn bản người dùng đưa thành sách nói nhiều giọng. Xem Sách nói.
"VieNeu làm được gì?" trong MCP server. Công cụ list_capabilities (trong
Claude và ChatGPT là một thẻ menu: bấm câu ví dụ để gửi) và năm prompt có sẵn.
Tham số tuỳ chọn của các công cụ giờ nhận cả null. Xem
MCP server.
Đã kết nối trước bản này? Hãy kết nối lại. App giữ danh sách công cụ lấy
từ lúc kết nối, nên công cụ mới chỉ hiện sau khi bạn ngắt kết nối VieNeu rồi
kết nối lại. Từ nay serverInfo.version của server đổi mỗi khi công cụ đổi
(1.2.0+<dấu vân tay>), cho các app làm mới theo nó. Xem
Xử lý sự cố.
Tìm giọng hiểu lời mô tả vai. Trong MCP server, search của list_voices
nhận đúng kiểu trợ lý hay viết, "giọng nam trầm ấm miền Bắc": giới tính và vùng
miền lấy từ thông tin của giọng, từ có dấu phải khớp đúng dấu, các từ như
"giọng" được bỏ qua, và khi không giọng nào có đủ mọi từ thì trả về các giọng
gần nhất kèm phần còn thiếu. Xem MCP server.
2026-10-01 — MCP server trả MP3 và có trình phát trong khung chat; X-Vieneu-Job-Id trên /v1/audio/speech
Mới
MCP server trả MP3 và phát ngay trong khung chat. Văn bản tới 1.500 ký tự giờ trả về MP3 (nhẹ khoảng 10 lần so với WAV), và trong Claude, ChatGPT kết quả hiện thành trình phát ngay trong cuộc trò chuyện. Xem MCP server.
POST /v1/audio/speech cho biết mã của bản lưu. Response thành công (không
stream) có thêm header X-Vieneu-Job-Id: mã mà VieNeu dùng để lưu một bản của
audio bạn vừa nhận. Giây lát sau, GET /v1/tts/{jobId} trả completed kèm
audioUrl đã ký sẵn cho đúng những byte đó — tiện khi bạn cần link để chia sẻ
thay vì file thô. Header này được mở cho trình duyệt đọc qua CORS.
GET /v1/balance. Số token key đang gọi tiêu được ngay lúc này, gói mà nó
trừ, và hạn mức ngày/tuần của gói kèm giờ làm mới. Không trừ token. MCP server
có cùng thông tin qua công cụ get_token_balance, và báo số token còn lại sau
mỗi lần tạo audio xong.
Đăng nhập MCP dùng được với ChatGPT. Máy chủ xác thực giờ nhận metadata
document ưu tiên private_key_jwt miễn là nó cũng cho phép none (ChatGPT là
vậy), và đăng ký động nhận client_secret_post / client_secret_basic.
2026-09-30 — MCP server chạy sẵn: dùng VieNeu ngay trong Claude và ChatGPT
Mới
https://api.vieneu.io/mcp — thêm địa chỉ này vào Claude, ChatGPT, Cursor
hoặc Claude Code, đăng nhập tài khoản VieNeu, rồi nhờ đọc tiếng Việt bằng lời
thường. Trợ lý tự tìm giọng, tạo audio và trả link tải. Không cần cài gói, không
cần dán API key: trợ lý đăng nhập qua OAuth 2.1 và bạn cho phép trên một trang
của VieNeu. Mỗi lần gọi công cụ tính phí đúng như lời gọi /v1 tương ứng. Xem
MCP server và hướng dẫn cho từng app:
Claude, ChatGPT
và các app khác.
Danh sách app đã kết nối, và nút gỡ kết nối, nằm ở trang Nhà phát triển.
2026-09-25 — Trúng cache thì POST /v1/tts trả completed ngay
Mới
POST /v1/tts trả luôn link audio khi audio đã có sẵn. Yêu cầu giống hệt
nhau — cùng text, giọng, tốc độ, cảm xúc và engine, từ bất kỳ tài khoản nào —
được phục vụ từ cache nội dung thay vì tổng hợp lại. Trước đây lời gọi như vậy
vẫn trả status: "queued" như mọi lời gọi khác, đẩy bạn đi poll một đoạn audio
đã có sẵn: mất trọn một chu kỳ poll cho không.
Nay nó trả status: "completed" kèm audioUrl, audioUrlExpiresIn và
duration — đúng body mà GET /v1/tts/{jobId} sẽ trả — nên không còn gì để
poll. Cách tính phí không đổi (trúng cache vẫn trừ token như trước).
Nếu client của bạn luôn poll sau khi gửi thì không hỏng gì: lần poll trả về cùng
body completed. Muốn tận dụng đường tắt, rẽ nhánh theo status ở response gửi:
const job = await submit(text, voiceId);
const done = job.status === 'completed' ? job : await pollUntilDone(job.jobId);
Lời gọi không trúng cache vẫn trả queued — replay theo Idempotency-Key của
một lần gửi trước cũng vậy, bất kể job đó đang ở trạng thái nào; hãy poll nó.
Thi thoảng file của bản cache vẫn đang trên đường lên kho lưu trữ; khi đó
response giữ queued và lần poll sau đó một chút sẽ báo completed.
2026-09-24 — v3 rút khỏi Cloud API
⚠️ Thay đổi hành vi
Engine v3 không còn trên /api/v1. Từ 08:00 ngày 2026-09-24 (GMT+7),
Cloud API chỉ dựng tiếng bằng v4. Bất kỳ request nào nêu "engine": "v3" —
trên POST /v1/tts, /v1/tts/stream, /v1/audio/speech, /v1/dialogue,
/v1/dub, /v1/srt và các biến thể multipart của chúng — đều bị từ chối với
400 trước khi bất cứ khoản nào bị tính, và thông báo nói rõ:
Engine "v3" was retired on 2026-09-24. Use engine "v4" and a voice from GET /v1/voices?engine=v4 — the two catalogues share no ids.
Request không nêu engine thì vốn đã rơi vào v4, engine mặc định, nên không bị
ảnh hưởng — trừ khi nó mang theo một voice id của v3, là điểm kế tiếp.
Các endpoint danh mục giờ trả gì. GET /v1/engines liệt kê đúng một engine,
{ "key": "v4", "isDefault": true, "sampleRate": 48000, "billingMultiplier": 3, "features": ["generate", "clone", "dialogue", "stream", "dub", "srt"] }, kèm
"globalMultiplier": 1.3 bên cạnh. GET /v1/voices chỉ liệt kê giọng v4,
cộng thêm các bản nhân bản v4 của chính bạn khi gửi kèm key; giọng v3, và
bản nhân bản đăng ký trên v3, không còn được liệt kê. GET /v1/voices?engine=v3
là 400 với thông báo ở trên. Id của danh mục đã ngừng — phần lớn là slug
vieneu-… khó đọc — gần như không chung không gian với tên hiển thị của v4,
nên một giọng v3 hard-code sẵn vẫn tiếp tục lỗi ở voiceId kể cả khi bạn đã
bỏ engine: hãy lấy một id mới từ GET /v1/voices?engine=v4.
Trên route tương thích OpenAI, "model": "vieneu-v3" trả 400 kèm
Model 'vieneu-v3' is retired. Engine "v3" was retired on 2026-09-24. ….
tts-1, tts-1-hd, gpt-4o-mini-tts, vieneu và vieneu-v4 đều trỏ về v4.
Trường emotion (natural / storytelling) vốn chỉ dành cho v3; nó vẫn được
nhận, rồi bị bỏ qua — v4 không có kiểu đọc.
GET /v1/emotion-tags không kèm engine giờ trả lời cho engine mặc định,
v4: không có kiểu đọc và ba thẻ biểu cảm đặt trong văn bản, [cười],
[thở dài] và [hắng giọng]. Trước đây nó trả bộ của v3. ?engine=v3 là
400. Các endpoint /v1/audio/… tương ứng cũng vậy.
Bản nhân bản đăng ký trên v3 — mọi giọng tạo trước 2026-08-28, thời điểm
việc đăng ký chuyển sang v4 — không còn dựng tiếng được qua API, vì engine duy
nhất đọc được đoạn mẫu của chúng chính là engine giờ trả 400. Gửi một id như
vậy làm voiceId (hay voice của /v1/audio/speech) sẽ nhận 400 kèm
code: "CLONE_ENGINE_RETIRED" và engine của giọng, thay vì bị âm thầm dựng
trên v4 bằng một chất giọng bạn chưa từng đăng ký. Hãy đăng ký lại
giọng trên Studio; id clone_… mới chạy trên
POST /v1/tts và POST /v1/tts/stream y như trước.
Những gì không bị ảnh hưởng. Audio đã tạo trên v3 vẫn nguyên — các mục
trong thư viện và link tải vẫn hoạt động. Và đây chỉ là thay đổi của Cloud API:
bản v3 Turbo chạy tại chỗ trong Python SDK và ứng dụng Windows chạy trên máy
của bạn, không đổi gì.
2026-09-23 — Nhân bản giọng chuyển hẳn về Studio web
⚠️ Thay đổi hành vi
Các endpoint tạo giọng nhân bản đã đóng. POST /v1/voices,
DELETE /v1/voices/{voiceId}, POST /v1/clone, POST /v1/upload và
POST /v1/prepare nay trả 410 kèm code: "CLONE_WEB_ONLY" và cloneUrl.
Không trừ token, không chạm tới GPU — lỗi từ chối xảy ra trước cả hai việc đó.
Hãy tạo giọng tại vieneu.io/#/clone.
Vì sao đưa về web: nhân bản cho ra giọng tốt là việc cần có người dẫn. Studio khử nhiễu clip, chép lời bằng Whisper và cho bạn nghe thử trước khi lưu. Một clip mẫu ồn, chép lời sai hoặc sai độ dài sẽ làm hỏng mọi lần tạo tiếng sau này bằng giọng đó chứ không riêng lần tạo giọng — mà gọi qua API thì không cách nào thấy được điều đó trước khi đã trả phí tạo giọng.
Phần tạo tiếng không đổi gì. Giọng nhân bản trên web vẫn hiện trong
GET /v1/voices khi bạn gửi kèm key ("kind": "cloned"), và id clone_… vẫn là
một voiceId bình thường ở POST /v1/tts và POST /v1/tts/stream, giá đúng
bằng giọng catalogue. Hệ tích hợp nào chỉ DÙNG giọng nhân bản thì không phải sửa
gì cả.
Các route nhân bản đã được gỡ khỏi /openapi.json và
tài liệu tham chiếu API, nên client sinh tự động sẽ mất chúng ở
lần sinh lại kế tiếp. Các code lỗi nhân bản cũ (CLONE_MONTHLY_CAP,
CLONE_QUOTA_EXCEEDED, CLONE_REF_*, …) thuộc về các route đó nên không còn tới
được một API key nữa; những trần theo gói ấy vẫn áp nguyên trên Studio. Xem
Lỗi → Nhân bản giọng.
2026-09 — Body lỗi, code hạn mức, và cổng engine khi tạo giọng nhân bản
⚠️ Thay đổi hành vi — chỉ thêm vào, không bỏ đi gì
Đọc dòng này trước đã: không có trường nào bị bỏ, bị đổi tên, hay đổi kiểu dữ liệu lẫn ý nghĩa. Cả ba thay đổi dưới đây chỉ thêm nội dung vào những body vốn đã được gửi. Thứ duy nhất có thể nhận ra khác biệt là một tích hợp từ chối trường lạ — một schema chặt, hay một struct Go giải mã có bật kiểm tra trường không khai báo — và đó chính là lý do mục này được xếp vào thay đổi hành vi thay vì phần Mới.
Mọi body lỗi dạng gốc trên /v1 giờ đều mang statusCode. Trước đây trường
này chỉ có ở những body không mang gì khác: ngay khi một lỗi từ chối có thêm code
máy đọc được thì nó mất statusCode — tức là đổi lấy một lý do máy đọc được thì
mất đi một trường bạn vẫn luôn đọc được. Giờ chỉ còn một dạng duy nhất, trên mọi
lỗi mà envelope của nền tảng bao phủ. Dòng status của HTTP vẫn là bản chuẩn.
POST /v1/audio/speech không bị ảnh hưởng — route đó trả lời bằng envelope của
OpenAI, vốn không có statusCode.
Lỗi hạn mức giờ mang code, kèm resetAt, remaining và required ở những chỗ
bước trừ token cung cấp được. Tám chỗ từ chối trên bảy route có tính tiền —
/v1/tts, /v1/tts/stream, /v1/dialogue, /v1/dub (hai chỗ: cổng kiểm khả
năng chi trả trước khi tốn GPU, và bước trừ tiền sau đó), /v1/clone, /v1/srt
và /v1/vapi/speech — trước đây chỉ ném ra một câu trần trụi, nên cách duy nhất để
phân biệt "nạp thêm" với "chờ một tiếng" là dò câu chữ tiếng Anh. Giờ chúng mang
GRANT_EXPIRED, GRANT_TOKENS_EXHAUSTED, GRANT_DAILY_LIMIT,
GRANT_WEEKLY_LIMIT hoặc CONCURRENT_CONFLICT, và hai loại trần tự phục hồi thì
kèm resetAt theo chuẩn ISO 8601 nói rõ khi nào hết. message giữ nguyên, nên một
client chỉ đọc mỗi trường đó vẫn chạy như cũ. Xem
Lỗi để biết từng code nghĩa là gì và phải làm gì.
POST /v1/voices giờ kiểm đúng engine sẽ thực sự chạy. Tạo giọng nhân bản chỉ
còn chạy trên v4 từ 2026-08-28, nhưng chốt kiểm ở cửa vào vẫn đang khẳng định
những điều về v3 — nên một lượt tạo giọng không ghi engine nào vẫn có thể bị từ
chối vì tình trạng của một engine nó không bao giờ dùng tới. Giờ phép kiểm chạy
trên đúng engine mà request sẽ dùng để tạo giọng, và chỉ chạy khi bạn ghi rõ engine.
- Bạn sẽ thấy: một lượt tạo giọng bỏ trống
engine— tức đường đi bình thường — không còn hỏng vì những lý do chẳng liên quan gì tới nó. - Không có gì đổi: ghi rõ
"engine": "v3"thì vẫn bị từ chối với400 CLONE_ENGINE_NOT_ALLOWED, và ghi rõ một engine mà gói của bạn không có thì vẫn là403.
2026-09 — Webhooks
Mới
Webhooks cho tác vụ bất đồng bộ. Đăng ký một endpoint https bằng
POST /v1/webhooks, và thay vì polling GET /v1/tts/{jobId}, bạn nhận
tts.job.completed hoặc tts.job.failed ngay khi job kết thúc. Sự kiện mang đủ
thông tin để xử lý mà không cần gọi thêm, kèm một URL tải audio có hiệu lực một
giờ.
- Ký bằng HMAC-SHA256 trong header
Vieneu-Signature: t=…,v1=…— cùng khuôn với Stripe, nên bộ kiểm chữ ký bạn đã viết dùng lại được gần như nguyên vẹn. ĐoạnverifySignaturechép-dán-là-chạy có trong Webhooks. - Gửi ít nhất một lần và không theo thứ tự. Trùng lặp là chuyện bình thường:
hãy khử trùng lặp theo
id(ổn định theo từng job + loại sự kiện). Đừng khử trùng lặp theo chữ ký — mỗi lần thử đều được ký lại nêntvàv1đều đổi. - Một lần gửi hỏng sẽ được thử lại, tổng cộng tối đa 6 lượt, ở các mốc
t+0,+0.5m,+2.0m,+5.5m,+13.0m,+28.5m— tức khoảng 28,5 phút cho cả loạt, và khoảng cách dài nhất giữa hai lần thử là 15,5 phút. (Mục này ban đầu ghi "khoảng 15 phút"; đó là tính nhầm công thức backoff, xem Webhooks.) Hãy đặt mọi ngưỡng đối soát trên 15,5 phút. Hết lượt thử thì sự kiện bị đưa vào dead-letter: không gửi lại nữa, tài khoản của bạn nhận một thông báo, vàGET /v1/webhooks/{id}/deliveriescho biết vì sao. Audio không mất —GET /v1/tts/{jobId}vẫn trả về job và một URL tải mới. - Endpoint phải là
httpsvà phải trỏ tới địa chỉ công khai. Dải IP riêng, loopback, link-local, CGNAT và các dải dành riêng đều bị từ chối — cả lúc đăng ký lẫn tại đúng thời điểm gửi. Mọi phản hồi3xxbị tính là gửi hỏng. - Xoay signing secret bằng
POST /v1/webhooks/{id}/rotate-secret. Secret cũ còn hiệu lực 24 giờ và mỗi sự kiện mang mộtv1=cho mỗi secret còn hiệu lực, nên bạn triển khai secret mới mà không rớt sự kiện nào.
Không có gì thay đổi hành vi: polling vẫn chạy y hệt, và tài khoản chưa đăng ký endpoint nào thì không thấy khác biệt gì.
2026-08 — Định dạng đầu ra, tương thích OpenAI, và Vapi
Mới
Giọng nhân bản chạy được trên POST /v1/tts/stream. Truyền id clone_…
(lấy từ GET /v1/voices, tạo bằng POST /v1/voices) vào voiceId là stream
được, y như một giọng có sẵn. Trước đây đường stream từ chối mọi id clone_…
trong khi ứng dụng web đã stream giọng nhân bản từ lâu — worker vốn hỗ trợ,
chỉ có bề mặt công khai là chặn.
- Tính tiền không đổi: vẫn theo số ký tự gửi lên × hệ số của engine. Giọng
nhân bản không có phụ phí riêng; khoản duy nhất là phí ghi danh một lần ở
POST /v1/voices. - Giọng nhân bản gắn với đúng engine lúc ghi danh, nên quy tắc "stream chỉ chạy
v4" vẫn áp dụng. Clone mới đều ghi danhv4. - Không phải là thay đổi hành vi: những gì chạy được hôm qua vẫn chạy y hệt.
Nhiều định dạng đầu ra. POST /v1/tts/stream và POST /v1/audio/speech giờ
nhận mp3, opus, pcm (thô, không header) và ulaw (G.711 8 kHz cho tổng
đài), kèm chọn sample rate. Trước đây chỉ có WAV 48 kHz. mp3 nhỏ hơn WAV khoảng
6 lần.
POST /v1/audio/speech là bản drop-in thật sự cho OpenAI. Trỏ SDK OpenAI vào
https://api.vieneu.io/api/v1 với API key của bạn là chạy, không sửa gì thêm.
speed đã được áp dụng, model chọn engine, và stream_format cho phép nhận
audio ngay trong lúc đang tạo (chunked hoặc SSE kiểu OpenAI). Thêm
GET /v1/audio/voices để các client OpenAI lấy danh sách giọng.
POST /v1/vapi/speech — webhook custom-voice cho Vapi.
Trỏ custom-voice của assistant vào URL này là agent thoại của bạn nói tiếng
Việt. Chi tiết trong Tích hợp Vapi.
Header hạn mức trên mọi phản hồi. X-RateLimit-Limit,
X-RateLimit-Remaining, X-RateLimit-Reset, và X-Request-Id — hãy đưa kèm
X-Request-Id khi liên hệ hỗ trợ, đó là id dùng để tra log của chúng tôi.
Tài liệu công khai. Mục Cloud API trên docs.vieneu.io, kèm decoder tham chiếu Python và JavaScript cho streaming.
⚠️ Thay đổi hành vi
aiRefine mặc định chuyển từ BẬT sang TẮT.
Bước tinh chỉnh bằng AI (kiểm duyệt nội dung + chuẩn hoá phát âm cho công thức,
từ viết tắt, tiếng Anh xen kẽ) trước đây chạy mặc định trên /v1 và tính thêm
phụ phí. Giờ bạn phải chủ động bật bằng "aiRefine": true.
- Bạn sẽ thấy gì: chi phí mỗi request giảm, độ trễ giảm, và văn bản được đọc đúng như bạn gửi.
- Nếu bạn muốn giữ hành vi cũ: thêm
"aiRefine": truevào request. VớiPOST /v1/srt(multipart) là trườngaiRefine=true. - Chuẩn hoá văn bản tất định (cách đọc hoá học, gộp CHỮ HOA, tầng phiên âm sea-g2p) vẫn chạy trong mọi trường hợp — tiếng Việt vẫn đọc đúng.
Mặc định của response_format trên /v1/audio/speech chuyển từ wav sang
mp3. Đây là mặc định của OpenAI, và một client OpenAI bỏ trống trường này là
đang mong đợi mp3. Nếu bạn cần WAV, gửi "response_format": "wav".
Hạn mức đổi đơn vị: từ mỗi IP sang mỗi API key. Trước đây đếm theo địa chỉ IP, nghĩa là một văn phòng dùng chung mạng phải chia nhau hạn mức, còn một key chạy trên nhiều máy thì được nhân lên. Giờ đếm theo key — đúng thứ bạn mua. Đi kèm, trần của ba route tổng hợp chính đã được nâng lên 300 request/phút để không ai bị hụt so với trước.
Đây là hạn mức của tầng ứng dụng. Đứng trước nó là một proxy biên vẫn đếm
theo địa chỉ nguồn, và tầng đó không đổi. Cách phân biệt: 429 có kèm
X-RateLimit-* là key của bạn chạm trần ứng dụng; 429/503 trần trụi không
mang header nào là proxy biên chặn theo IP — dùng chung với mọi người đứng sau
địa chỉ đó. Xem Hạn mức.
Sửa lỗi
- Streaming qua
api.vieneu.iokhông còn bị proxy đệm lại — audio đến ngay khi được tạo, đúng như thiết kế. POST /v1/tts/streamgiờ báo đúng định dạng và sample rate thật trong headerX-Output-Format/X-Sample-Rate, thay vì lặp lại thứ bạn yêu cầu.- Stream bị cắt giữa chừng được hoàn tiền đáng tin cậy hơn: một stream kết thúc đúng quy cách nhưng không mang audio nào giờ cũng được hoàn.
Giới hạn đã biết
stream_format (và streaming nói chung) chỉ nên dùng với pcm và ulaw. Các
khung audio được mã hoá độc lập nhau, nên nối mp3 lại sẽ có khoảng lặng ở mỗi
mối nối, còn opus trở thành một chuỗi stream Ogg mà phần lớn trình duyệt chỉ
phát được stream đầu tiên. Cần một file mp3 hoặc opus hoàn chỉnh thì gửi request
thường, không streaming.