Voices + Media files
Hai nhóm tài nguyên dùng chung trong AutoCall:
- Voices — danh sách giọng đọc TTS khả dụng để dùng
voice_idkhi tạo script. - Media files — file âm thanh (.wav/.mp3/...) dùng làm
target_audio_urlcho DTMF actionplayback/playback_then_hangup.
List voices dùng được trong AutoCall (KHUYẾN NGHỊ cho integration)
GET /api/autocall/voicesMục đích: trả về danh sách chỉ voice khả dụng. Đây là voice đảm bảo render preview/dial được — KHÔNG bị lỗi Voice không khả dụng như khi pick voice tuỳ ý từ provider.
Response 200 (chỉ 5 field cần thiết cho client):
{
"data": [
{
"id": "voice_id_premium_02",
"name": "vi-VN-female-01",
"preview_url": "https://app.zorio.vn/api/autocall/voices/preview",
"gender": "female",
"language": "vi"
}
]
}Field response:
| Field | Type | Mô tả |
|---|---|---|
id | string | Voice ID — dùng làm voice_id khi POST /api/autocall/scripts |
name | string | Tên hiển thị friendly |
preview_url | string | null | URL mp3 sample để play thử (preview audio) |
gender | string | null | male / female |
language | string | null | vi / en / ... |
Fallback khi provider lỗi
Nếu provider integration tạm thời không phản hồi (network/api key), endpoint vẫn trả về voice đó với chỉ field id + name=id để client KHÔNG bị lỗi — UI có thể fallback hiển thị ID raw.
Tier A vs Tier B
- Tier A = premium nhà cung cấp TTS cao cấp realtime (charge ký tự).
- Tier B = local pre-rendered vi-VN-female-01 (không phí, throughput cao). Khuyến nghị default cho khối lượng lớn.
tts_tier cấu hình ở level script (xem Scripts). Hệ thống tự routing theo voice_id -> provider tương ứng.
Media Files (Mẫu ghi âm)
Module Media Files chuẩn của Zorio — dùng để upload file âm thanh (.wav/.mp3/.m4a/...) và auto-convert sang WAV 16-bit PCM 8kHz mono. Trong AutoCall, dùng file_path của media file làm target_audio_url cho DTMF action playback / playback_then_hangup.
Category enum:
announcement— thông báo cho DTMF action (vd "Cảm ơn anh/chị", "Đang chuyển nhân viên...")ivr— prompt IVR (chào, menu...)moh— music on holdlibrary— tổng quát
Permission
Cần manage_recordings hoặc admin để upload/sửa/xoá; viewer có thể list + lấy audio.
List media files
GET /api/media-files?category=announcementQuery:
| Param | Type | Mô tả |
|---|---|---|
category | string, optional | Filter theo enum ivr / moh / announcement / library. Bỏ qua -> trả tất cả |
Response 200:
{
"data": [
{
"id": 20,
"tenant_id": 1,
"name": "VNT v2",
"file_path": "/media/ivr/studio-1776477792_1776477798_d939.wav",
"file_size": 176718,
"duration": 11,
"format": "wav",
"category": "ivr",
"tts_text": null,
"tts_voice": null,
"tts_provider": null,
"created_at": "2026-04-18 02:03:19"
}
]
}Field response:
| Field | Type | Mô tả | Giá trị hợp lệ |
|---|---|---|---|
data[].id | integer | ID media file | Số nguyên dương |
data[].tenant_id | integer | ID khách hàng sở hữu | — |
data[].name | string | Tên hiển thị | Tối đa 255 ký tự |
data[].file_path | string | Định danh file (dùng làm target_audio_url) cho DTMF action playback | Định danh nội bộ |
data[].file_size | integer | Kích thước file (byte) | > 0 |
data[].duration | integer | Thời lượng audio (giây) | >= 0 |
data[].format | string | Định dạng audio (luôn là wav sau convert) | wav |
data[].category | string | Phân loại file | ivr / moh / announcement / library |
data[].tts_text | string | null | Text gốc (chỉ != null nếu file synthesize qua TTS) | — |
data[].tts_voice | string | null | Voice ID (chỉ với TTS file) | — |
data[].tts_provider | string | null | Provider TTS đã dùng | tts_provider_01 / local / null |
data[].created_at | datetime | Thời điểm upload (UTC, format YYYY-MM-DD HH:mm:ss) | — |
Field metadata TTS
tts_text, tts_voice, tts_provider chỉ != null nếu file được synthesize qua TTS (không relevant cho file upload thủ công). Thông tin tham khảo, không bắt buộc xử lý.
Upload media file
POST /api/media-files
Content-Type: multipart/form-dataBody (multipart):
| Field | Required | Type | Mô tả |
|---|---|---|---|
file | Có | binary | File audio (.wav, .mp3, .m4a, .ogg, .aac, .flac). Max 50MB |
name | Có | string | Tên hiển thị (vd "Cảm ơn quý khách") |
category | Không | enum | ivr / moh / announcement / library. Default library |
Request mẫu (curl):
curl -X POST https://app.zorio.vn/api/media-files \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json" \
-F "file=@cam-on.mp3" \
-F "name=Cảm ơn quý khách" \
-F "category=announcement"Response 201:
{
"data": {
"tenant_id": 1,
"name": "Test",
"file_path": "/media/library/test_1782374777.wav",
"file_size": 43704,
"duration": 3,
"format": "wav",
"category": "library",
"id": 21
},
"message": "File đã upload và convert thành công."
}Field response:
| Field | Type | Mô tả | Giá trị hợp lệ |
|---|---|---|---|
data.id | integer | ID media file vừa tạo | Số nguyên dương |
data.tenant_id | integer | ID khách hàng sở hữu | — |
data.name | string | Tên hiển thị | — |
data.file_path | string | Định danh file sau convert (WAV 16-bit PCM 8kHz mono) | Định danh nội bộ |
data.file_size | integer | Kích thước file đã convert (byte) | > 0 |
data.duration | integer | Thời lượng audio (giây) | >= 0 |
data.format | string | Định dạng sau convert | Luôn wav |
data.category | string | Phân loại file | ivr / moh / announcement / library |
message | string | Thông điệp xác nhận thành công | — |
Error 422 (file sai định dạng / quá lớn):
{
"message": "The file must be a file of type: wav, mp3, m4a, ogg, aac, flac.",
"errors": { "file": ["The file must be a file of type: wav, mp3, m4a, ogg, aac, flac."] }
}Error 500 (server thiếu engine chuyển đổi audio):
{ "error": "engine chuyển đổi audio chưa được cài đặt trên server" }Cập nhật metadata media file
PATCH /api/media-files/{id}Chỉ đổi name / category — KHÔNG đụng file vật lý.
Path params:
| Field | Type | Required | Mô tả | Giá trị hợp lệ |
|---|---|---|---|---|
id | integer | Có | ID media file cần cập nhật | Số nguyên dương |
Body:
{
"name": "Cảm ơn — phiên bản 2",
"category": "announcement"
}Body fields:
| Field | Type | Required | Mô tả | Giá trị hợp lệ |
|---|---|---|---|---|
name | string | Không | Đổi tên hiển thị | Tối đa 255 ký tự |
category | string | Không | Đổi phân loại | ivr / moh / announcement / library |
Response 200:
{
"data": {
"id": 21,
"tenant_id": 1,
"name": "Cảm ơn — phiên bản 2",
"file_path": "/media/library/test_1782374777.wav",
"file_size": 43704,
"duration": 3,
"format": "wav",
"category": "announcement",
"tts_text": null,
"tts_voice": null,
"tts_provider": null,
"created_at": "2026-06-25 08:06:17"
},
"message": "Đã cập nhật file âm thanh."
}Field response: shape giống GET /api/media-files item (xem table ở mục List media files) + thêm message ngoài data.
Thay thế file vật lý (giữ ID)
POST /api/media-files/{id}/replace
Content-Type: multipart/form-dataBackup file cũ thành <path>.bak-<timestamp> rồi ghi đè đúng file_path — IVR/DTMF action đang dùng target_audio_url không cần update vì path không đổi.
Path params:
| Field | Type | Required | Mô tả | Giá trị hợp lệ |
|---|---|---|---|---|
id | integer | Có | ID media file cần thay | Số nguyên dương |
Body (multipart):
| Field | Type | Required | Mô tả | Giá trị hợp lệ |
|---|---|---|---|---|
file | binary | Có | File audio mới | .wav, .mp3, .m4a, .ogg, .aac, .flac, max 50MB |
Response 200:
{
"data": {
"id": 21,
"tenant_id": 1,
"name": "Cảm ơn — phiên bản 2",
"file_path": "/media/library/test_1782374777.wav",
"file_size": 43704,
"duration": 3,
"format": "wav",
"category": "announcement",
"tts_text": null,
"tts_voice": null,
"tts_provider": null,
"created_at": "2026-06-25 08:06:17"
},
"backup": "test_1782374777.wav.bak-20260625-080956",
"message": "Đã thay file thành công. File cũ đã backup."
}Field response:
| Field | Type | Mô tả | Giá trị hợp lệ |
|---|---|---|---|
data | object | Object media file (shape giống GET /api/media-files item) | — |
backup | string | Tên file backup của bản cũ. Path full = dirname(file_path) + '/' + backup | <filename>.bak-<timestamp> |
message | string | Thông điệp xác nhận | — |
Field backup ở top-level
Không nằm trong data — chứa tên file backup. Đường dẫn full = dirname(file_path) + '/' + backup.
Xoá media file
DELETE /api/media-files/{id}Xoá record DB + file vật lý.
Response 200:
{ "message": "Đã xóa." }Audit trước khi xoá
Nếu file đang được DTMF action target_audio_url reference, dial sẽ fail với "file not found". Nên audit trước khi xoá.
Stream audio (play preview)
GET /api/media-files/{id}/audioTrả về binary stream WAV với Content-Type: audio/wav. Dùng trong <audio> tag HTML5 hoặc curl save:
curl -s https://app.zorio.vn/api/media-files/5/audio \
-H "Authorization: Bearer $TOKEN" \
-o cam-on.wav