آموزش Workflow تحلیل صندوق صوتی با n8n
این Workflow بهصورت خودکار پیامهای صوتی صندوق صوتی را پردازش میکند.
بعد از اینکه یک پیام صوتی در سیموتل ثبت شد، مراحل زیر انجام میشود:
- دریافت اطلاعات تماس
- دریافت فایل صوتی
- ارسال فایل به هوش مصنوعی ویرا
- انتظار تا پایان پردازش
- دریافت نتیجه تحلیل
- استخراج اطلاعات مهم
در پایان، اپراتور بدون گوش دادن به فایل صوتی، خلاصه تماس را مشاهده میکند.
پیشنیازها
قبل از استفاده از این Workflow موارد زیر باید آماده باشند.
- نصب n8n
- دسترسی به API تلینا
- دسترسی به API ویرا
آشنایی با ساختار Workflow
در n8n هر مستطیل یک Node نام دارد.
هر Node فقط یک کار انجام میدهد.
خروجی هر Node به Node بعدی ارسال میشود.
تنظیمات سمت تلینا
ایجاد رویداد API برای ارسال ویسمیل به n8n
برای ارسال خودکار رویداد پیام صوتی (Voicemail) به n8n، ابتدا وارد پنل مدیریت تلینا شوید و مسیر زیر را طی کنید:
تنظیمات ← حساب های API سپس روی API جدید و بعد افزودن رویداد API کلیک کنید.
در صفحه بازشده، تنظیمات را مطابق تصویر زیر تکمیل کنید.
ایجاد حساب API برای دانلود فایل صوتی
پس از دریافت رویداد در n8n، لازم است فایل صوتی ویسمیل از تلینا دانلود شود. برای این کار، n8n باید از طریق API به تلینا درخواست ارسال کرده و لینک دانلود فایل صوتی را دریافت کند.
برای ایجاد دسترسی API، در پنل تلینا به مسیر زیر بروید:
تنظیمات API ← سپس روی API جدید و بعد ایجاد اکانت API کلیک کنید.
در صفحه بازشده، اطلاعات را مطابق تصویر زیر وارد کنید.
در بخش دسترسیهای API ، گزینه مربوط به Voicemail را فعال کنید تا این حساب امکان دریافت لینک فایلهای صوتی را داشته باشد .تنظیمات این بخش باید مطابق تصویر زیر انجام شود.
دریافت API Key
پس از ایجاد حساب API، یک API Key برای شما تولید میشود. این کلید برای احراز هویت درخواستهای n8n به تلینا استفاده میشود و باید در Nodeهای مربوط به فراخوانی API در n8n وارد شود.
نمونه API Key تولیدشده در تصویر زیر نمایش داده شده است.
تنظیمات سمت n8n
مرحله اول Webhook
هدف
این Node نقطه شروع Workflow است.
هر زمان سیموتل یک پیام صوتی جدید دریافت کند، اطلاعات تماس را از طریق HTTP به این Webhook ارسال میکند و Workflow اجرا میشود.
تنظیمات Node
Path
voicemail
این مقدار آدرس Webhook را مشخص میکند.
در نتیجه آدرس زیر ایجاد میشود.
https://YOUR-N8N/webhook/voicemail
سیموتل باید اطلاعات صندوق صوتی را به همین آدرس ارسال کند.
HTTP Method
GET
زیرا سیموتل اطلاعات را بهصورت GET ارسال میکند.
Authentication
None
در این پروژه هیچ احراز هویتی برای Webhook تعریف نشده است.
در صورت نیاز میتوان Basic Auth یا Header Authentication نیز فعال کرد.
خروجی
Webhook اطلاعات زیر را دریافت میکند.
[
{
“headers” :{
“host”: “n8n……ir”,
“accept-encoding”: “gzip, deflate”,
“authorization”: “Basic dGVzdDoxMjM0”,
“connection”: “close”,
“x-real-ip”: “5…..171”,
“true-client-ip”: “5…..171”,
“x-forwarded-proto”: “https”,
“x-forwarded-port”: “443”,
“x-forwarded-for”: “5……171”,
“x-request-id”: “…………fa59dac142a2a31”,
“x-country-code”: “IR”,
“x-sid”: “2075”,
“ar-real-ip”: “5……171”,
“ar-real-country”: “IR”,
“ar-sid”: “2075”,
“user-agent”: “python-requests/2.24.0”,
“accept”: “/”,
“cdn-loop”: “arvancloud; count=1”
},
“params”: {},
“query”: {
“caller”: “0939…3404”,
“cuid”: “1782982024.11645”,
“date”: “2026-07-02 08:47:33.986753”,
“duration”: “18”,
“event_name”: “VoiceMail”,
“filename”: “311_1782982025-vm-record-file-4594.mp3”,
“id”: “6a4625a51366466a7022146c”,
“number”: “311”,
“state”: “SUCCESS”
},
“body”: {},
“webhookUrl”: “https://n8n…ir/webhook-test/voicemail”,
“executionMode”: “test”
}
]
مرحله دوم Get Audio Name (Code)
هدف
استخراج نام فایل صوتی از اطلاعات Webhook
تنظیمات Node
Language
JavaScript
Mode
Run Once for All Items
Code
return [
{
filename: $input.first().json.query.filename
}
];
این کد نام فایل صوتی را استخراج میکند.
خروجی
[
{
“filename”: “311_1782982025-vm-record-file-4594.mp3”
}
]
مرحله سوم Get Audio Link
هدف
دریافت لینک دانلود فایل از API سیموتل
تنظیمات Node
Method
POST
URL
https://panel.hostedpbx.ir/api/v4.1/voicemails/audio/download
این API لینک دانلود فایل را برمیگرداند.
Headers
X-APIKEY
مقدار این Header همان API Key پنل سیموتل است. بدون این Header درخواست رد خواهد شد.
مثلاً
X-APIKEY:xxxxxxxxxxxxxxxx
Body Type
JSON
Body
{
"file":
“{{$json.filename}}”
}
نام فایل از مرحله قبل دریافت میشود.
خروجی
[
{
“success”: 1,
“message”: “Requested operation is done successfully”,
“data”: {
}
}
]
مرحله چهارم Download Audio File
هدف
دانلود فایل صوتی.
تنظیمات Node
Method
GET
URL
{{$json.data.audioLink}}
این مقدار از مرحله قبل دریافت میشود.
خروجی
مرحله پنجم Send To Vira
هدف
ارسال فایل صوتی به هوش مصنوعی ویرا.
تنظیمات Node
Method
POST
URL
https://api.vira-id.ir/webhook/call/create
Headers
Authorization
Bearer YOUR_API_KEY
Body Type
Form Data
پارامتر اول
Name: audio
Type: Binary
Input Data Field Name:
data
همان فایل دانلود شده.
پارامتر دوم
Name: lang
Type: From data
Value: fa
مشخص میکند فایل فارسی است.
خروجی
ویرا یک شناسه پردازش برمیگرداند.
Id: 65895
مرحله ششم Request Status
هدف
بررسی وضعیت پردازش ویرا.
هر ۳ دقیقه یک درخواست وضعیت به ویرا ارسال میشود تا بررسی کند آیا صوت مربوط به id تولید شده در مرحله قبل تحلیل شده است و یا خیر اگر تحلیل کامل باشد complete:true میباشد و میتوان از محتوا استفاده کرد
تنظیمات
Method
GET
URL
https://api.vira-id.ir/webhook/call/details
Query Parameter
Specify Query Parameters: Using Fields Below
id
{{$json.result.id}}
Header
Authorization
Bearer YOUR_API_KEY
Accept
application/json
خروجی
اگر پردازش تمام نشده باشد
[
{
“success”: true,
“completed”: false,
“result”: {
“id”: 65895,
“title”: “Untitled”,
“duration”: 18.942,
“speakers”: null,
“summary”: “”,
“customer_satisfaction”:1,
“sections”: {
“raw”: “json\n[\n {\n \"end\": 3.73,\n \"text\": \"سلام وقت شما بخیر\",\n \"start\": 2.21,\n \"speaker\": \"speaker_0\"\n },\n {\n \"end\": 9.25,\n \"text\": \"من از سرویس شما استفاده میکنم سرویس خیلی خوبیه گزارشات خوبی میده و خیلی عالی هستش\",\n \"start\": 3.73,\n \"speaker\": \"speaker_0\"\n },\n {\n \"end\": 17.58,\n \"text\": \"و تمایل دارم که با شما همکاری کنم توی ارائه این محصول لطفاً با من در تماس باشید برای اطلاعات تکمیلی\",\n \"start\": 10.37,\n \"speaker\": \"speaker_0\"\n }\n]\n”
},
“token”: 12,
“created_at”: “2026-07-02T09:00:51.421Z”,
“prioritization”: {
},
“products”: [
]
}
}
]
اگر تمام شده باشد
[
{
“success”: true,
“completed”: true,
“result”: {
“id”: 65895,
“title”: “Untitled”,
“duration”: 18.942,
“speakers”: null,
“summary”: “مشتری از کیفیت سرویس و گزارشات آن ابراز رضایت کرده و تمایل دارد برای همکاری در ارائه محصول با سازمان در تماس باشد.”,
“customer_satisfaction”: 5,
“sections”: {
“raw”: “json\n[\n {\n \"end\": 3.73,\n \"text\": \"سلام وقت شما بخیر\",\n \"start\": 2.21,\n \"speaker\": \"speaker_0\"\n },\n {\n \"end\": 9.25,\n \"text\": \"من از سرویس شما استفاده میکنم سرویس خیلی خوبیه گزارشات خوبی میده و خیلی عالی هستش\",\n \"start\": 3.73,\n \"speaker\": \"speaker_0\"\n },\n {\n \"end\": 17.58,\n \"text\": \"و تمایل دارم که با شما همکاری کنم توی ارائه این محصول لطفاً با من در تماس باشید برای اطلاعات تکمیلی\",\n \"start\": 10.37,\n \"speaker\": \"speaker_0\"\n }\n]\n”
},
“token”: 12,
“created_at”: “2026-07-02T09:00:51.421Z”,
“prioritization”: {
“conversion_chance”: 80,
“loss_chance”: 0,
“urgency”: 3,
“required_effort”: “medium”
},
“products”:
}
}
]
به همراه اطلاعات تحلیل.
مرحله هفتم IF
هدف
بررسی پایان پردازش.
تنظیمات
Condition
{{$json.completed}}
Operator
Equals
Value
true
عملکرد
اگر نتیجه True باشد Workflow ادامه پیدا میکند.
اگر False باشد Node Wait اجرا میشود.
مرحله هشتم Wait
هدف
صبر کردن قبل از بررسی مجدد.
تنظیمات
Duration
180 Seconds
بعد از ۳ دقیقه دوباره Request Status اجرا میشود.
مرحله نهم Merge
هدف
ترکیب اطلاعات تماس اولیه با نتیجه تحلیل ویرا.
تنظیمات
Mode
Combine
Combine By
Combine by Position
دلیل استفاده: یک شاخه اطلاعات تماس را نگه داشته است و شاخه دیگر نتیجه تحلیل را تولید میکند. این Node هر دو را در یک خروجی واحد ادغام میکند.
مرحله دهم Finish (Code)
هدف
تبدیل اطلاعات خام ویرا به اطلاعات قابل استفاده است.
در این مرحله:
- متن مکالمه استخراج میشود.
- تاریخ و ساعت تبدیل میشوند.
- خلاصه تماس آماده میشود.
- احتمال از دست رفتن مشتری استخراج میشود.
- میزان رضایت مشتری استخراج میشود.
- میزان فوریت استخراج میشود.
- احتمال تبدیل مشتری استخراج میشود.
در پایان خروجی مرتب شدهای تولید میشود
کد جاوا اسکریپت
const data = $input.first().json;
const query = data.query;
const analysis = data.result;
let raw = analysis.sections.raw;
raw = raw
.replace(/^```json\s*/i, “”)
.replace(/```$/i, “”)
.trim();
const sections = JSON.parse(raw);
const transcript = sections
.map(item => item.text)
.join(" ");
const dateObj = new Date(query.date);
const date = dateObj.toISOString().split(“T”)[0];
const time = dateObj.toTimeString().split(" ")[0];
return [
{
json: {
call: {
caller: query.caller,
mailbox: query.number,
date: date,
time: time,
filename: query.filename
},
analysis: {
summary: analysis.summary,
transcript: transcript,
customer_satisfaction: analysis.customer_satisfaction,
loss_chance: analysis.prioritization.loss_chance,
conversion_chance: analysis.prioritization.conversion_chance,
urgency: analysis.prioritization.urgency,
equired_effort: analysis.prioritization.required_effort,
}
}
}
];
خروجی
[
{
“call”: {
“caller”: “0939…3404”,
“mailbox”: “311”,
“date”: “2026-07-02”,
“time”: “08:47:33”,
“filename”: “311_1782982025-vm-record-file-4594.mp3”
},
“analysis”: {
“summary”: “مشتری از کیفیت سرویس و گزارشات آن ابراز رضایت کرده و تمایل دارد برای همکاری در ارائه محصول با سازمان در تماس باشد.”,
“transcript”: “سلام وقت شما بخیر من از سرویس شما استفاده میکنم سرویس خیلی خوبیه گزارشات خوبی میده و خیلی عالی هستش و تمایل دارم که با شما همکاری کنم توی ارائه این محصول لطفاً با من در تماس باشید برای اطلاعات تکمیلی”,
“customer_satisfaction”: 5,
“loss_chance”: 0,
“conversion_chance”: 80,
“urgency”: 3,
“equired_effort”: “medium”
}
}
]















