·19 daq·1 ko'rish

Asterisk'da qo'ng'iroq yozuvlari analitikasini qanday sozlash kerak: to'liq qo'llanma

Xom qo'ng'iroq yozuvlarini amaliy xulosalarga aylantiring: saqlash arxitekturasi, CDR bilan bog'lash, SQL analitika, Whisper bilan AI transkripsiya va compliance amaliyotlari.

A
Astervis
Muhandislar va product jamoasi

Asterisk'da qo'ng'iroqlarni yozib olish oson. Lekin o'sha yozuvlardan amaliy foyda olish — aksariyat jamoalar aynan shu joyda qoqiladi.

Agar siz dialplan'da MixMonitor yoki Monitor'ni allaqachon sozlagan bo'lsangiz, qo'lingizda ma'lumotlar oltin koni turibdi. Muammo shundaki, ko'pchilik Asterisk o'rnatmalarida yozuvlar compliance uchun qo'yiladigan belgi sifatida qaraladi: fayllar /var/spool/asterisk/monitor/ ichida yotadi va nizoli holat chiqmaguncha ularga hech kim tegmaydi.

Bu qo'llanmada xom qo'ng'iroq yozuvlarini tuzilgan analitika tizimiga qanday aylantirish ko'rsatiladi. Siz yozuvlarni tez qidiruv uchun qanday tashkil qilishni, ularni CDR metama'lumotlari bilan bog'lashni, sifat muammolarini o'zi ko'rsatib beradigan dashboard'lar qurishni va hatto open-source vositalar yordamida AI nutq analitikasini qo'shishni o'rganasiz.

Nega qo'ng'iroq yozuvlari analitikasi kerak

Analitikasiz qo'ng'iroq yozuvi — bu videokuzatuv kameralarini o'rnatib, yozuvlarni hech qachon ko'rmaslik bilan barobar.

Yozuvlar analitikasi nima beradi:

StsenariyAnalitikasizAnalitika bilan
Sifat nazoratiTasodifiy tekshiruvlar (2-5% qamrov)Qo'ng'iroqlarning 100% bo'yicha tizimli baholash
Operatorlarni o'qitishXotiraga tayangan subyektiv fikrAniq misollar bilan ma'lumotga asoslangan o'qitish
Compliance tekshiruviShikoyat kelganda qo'lda ko'rib chiqishQoidabuzarliklarni avtomatik belgilash
Mijozlarni tushunishTarqoq kuzatuvlarMinglab murojaat bo'yicha trend tahlili
Nizolarni hal qilishFayl tizimi bo'ylab qo'lda qidirishQo'ng'iroq metama'lumotlari orqali bir zumda topish

Qo'ng'iroq yozuvlari analitikasidan foydalanayotgan kompaniyalar joriy etishning birinchi choragidayoq birinchi qo'ng'iroqda hal qilish ko'rsatkichi 23% ga yaxshilanganini va o'rtacha ishlov berish vaqti 18% ga qisqarganini qayd etadi (ICMI Contact Center Research, 2024).

1-qadam. Poydevor: yozib olishni sozlash

Analitika qurishdan oldin yozib olishning mustahkam poydevori kerak. Asterisk ikkita asosiy ilova taklif qiladi:

MixMonitor va Monitor solishtiruvi

XususiyatMixMonitorMonitor
Audio miksiIkkala tomonni bitta faylga yozadiYo'nalishlar bo'yicha alohida fayllar (yoki miksangan)
Unumdorlikka ta'siriYengil (tavsiya etiladi)Og'irroq, ovoz muammolari bo'lishi mumkin
Qo'ng'iroq davomida boshqaruvDinamik start/stop/pauzaCheklangan boshqaruv
Yozuv formatlariWAV, WAV49, GSM, SLN, SLINWAV, WAV49, GSM
Kanal talabiJavob berilgan kanallarda ishlaydiJavob berilgan kanallarda ishlaydi
Kimga tavsiya etiladiIshlab chiqarishdagi call-markazlargaLegacy o'rnatmalarga

MixMonitor'dan foydalaning. Bu zamonaviy va production'ga tayyor variant.

MixMonitor bilan oddiy dialplan

; extensions.conf — Recording with structured filenames [macro-record-call] exten => s,1,NoOp(Starting call recording) same => n,Set(RECORD_DIR=/var/spool/asterisk/monitor/${STRFTIME(${EPOCH},,%Y/%m/%d)}) same => n,System(mkdir -p ${RECORD_DIR}) same => n,Set(RECORD_FILE=${RECORD_DIR}/${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${UNIQUEID}-${CALLERID(num)}-${EXTEN}) same => n,Set(CDR(recordingfile)=${RECORD_FILE}.wav) same => n,MixMonitor(${RECORD_FILE}.wav,b) same => n,MacroExit()

Bu dialplan'dagi asosiy nuqtalar:

  • Sana bo'yicha kataloglar (YYYY/MM/DD) bitta papkada juda ko'p fayl to'planib, fayl tizimi sekinlashib qolishining oldini oladi
  • Tuzilgan fayl nomlari vaqt belgisi, unikal ID, qo'ng'iroq qiluvchi raqami va ichki raqamni o'z ichiga oladi — bu analitika uchun juda muhim
  • CDR bilan bog'lanish CDR(recordingfile) orqali yozuvni qo'ng'iroq tafsilotlari yozuviga ulaydi

FreePBX'da yozib olishni sozlash

Agar siz FreePBX'dan foydalansangiz, yozib olish har bir ichki raqam, ring group yoki navbat uchun alohida sozlanadi:

  1. Admin → Extensions → [Extension] → Recording bo'limiga o'ting
  2. Yozib olish siyosatini tanlang: Force, Don't Care, Yes yoki No
  3. Inbound External, Outbound External, Inbound Internal, Outbound Internal variantlaridan birini tanlang

FreePBX yozuvlarni /var/spool/asterisk/monitor/ ichida quyidagi formatda saqlaydi:

{year}/{month}/{day}/{type}-{date}-{time}-{source}-{destination}-{uniqueid}.wav

2-qadam. Analitika uchun saqlash arxitekturasi

Production'dagi call-markaz yozuv tizimi uchun saqlashni puxta rejalashtirish kerak. 64 kbit/s (G.711 WAV) tezlikda bir soatlik yozilgan suhbat taxminan 28,8 MB joy egallaydi. Har bir operatorga kuniga o'rtacha 6 soat suhbat vaqti to'g'ri keladigan 50 operatorli call-markaz kuniga 8,6 GB, oyiga esa 260 GB hosil qiladi.

Saqlash hajmi kalkulyatori

OperatorlarKuniga o'rt. suhbat soatiKunlik hajmOylik hajmYillik hajm
1051,4 GB43 GB516 GB
2553,6 GB108 GB1,3 TB
5068,6 GB260 GB3,1 TB
100617,3 GB518 GB6,2 TB
200634,6 GB1 TB12,4 TB

Tavsiya etilgan saqlash tuzilmasi

/var/spool/asterisk/ └── monitor/ ├── 2026/ │ ├── 01/ │ │ ├── 15/ │ │ │ ├── 20260115-093042-1705312242.1-2125551234-100.wav │ │ │ └── ... │ │ └── 16/ │ └── 02/ ├── compressed/ # Archived recordings (MP3/Opus) │ ├── 2025/ │ └── ... └── transcripts/ # AI-generated transcripts ├── 2026/ └── ...

Siqish strategiyasi

Arxiv uchun WAV fayllar keraksiz darajada katta. Avtomatik siqishni yo'lga qo'ying:

#!/bin/bash # compress-recordings.sh — Run daily via cron # Compresses WAV recordings older than 7 days to Opus format # Opus achieves 10:1 compression vs WAV with excellent quality MONITOR_DIR="/var/spool/asterisk/monitor" COMPRESS_DIR="$MONITOR_DIR/compressed" DAYS_OLD=7 find "$MONITOR_DIR" -name "*.wav" -mtime +$DAYS_OLD \ -not -path "*/compressed/*" | while read wavfile; do # Preserve directory structure relative_path="${wavfile#$MONITOR_DIR/}" opus_path="$COMPRESS_DIR/${relative_path%.wav}.opus" mkdir -p "$(dirname "$opus_path")" # Convert to Opus (high quality, ~1/10 the size) ffmpeg -i "$wavfile" -c:a libopus -b:a 24k \ -application voip "$opus_path" 2>/dev/null if [ $? -eq 0 ] && [ -f "$opus_path" ]; then rm "$wavfile" echo "Compressed: $relative_path" fi done

crontab'ga qo'shing:

# Run compression daily at 2 AM 0 2 * * * /usr/local/bin/compress-recordings.sh >> /var/log/recording-compression.log 2>&1

3-qadam. Yozuvlarni CDR metama'lumotlari bilan bog'lash

Xom yozuvlar CDR (qo'ng'iroq tafsilotlari yozuvi) ma'lumotlari bilan bog'langanda haqiqiy kuchga ega bo'ladi. Bu bog'lanish "kutish vaqti 60 soniyadan oshgan barcha yozuvlarni ko'rsat" yoki "shu mijoz raqamidan oxirgi 30 kundagi qo'ng'iroqlarni top" kabi so'rovlar qilish imkonini beradi.

Yozuvlar analitikasi uchun ma'lumotlar bazasi sxemasi

-- Create a recordings metadata table that extends CDR CREATE TABLE recording_metadata ( id SERIAL PRIMARY KEY, uniqueid VARCHAR(64) NOT NULL, linkedid VARCHAR(64), recording_path TEXT NOT NULL, recording_format VARCHAR(10) DEFAULT 'wav', file_size_bytes BIGINT, duration_seconds INTEGER, silence_percentage DECIMAL(5,2), caller_id VARCHAR(80), destination VARCHAR(80), queue_name VARCHAR(64), agent VARCHAR(64), direction VARCHAR(10), -- 'inbound', 'outbound', 'internal' disposition VARCHAR(20), recorded_at TIMESTAMP NOT NULL, compressed BOOLEAN DEFAULT FALSE, transcribed BOOLEAN DEFAULT FALSE, transcript_path TEXT, quality_score DECIMAL(3,1), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Indexes for common analytics queries CONSTRAINT unique_recording UNIQUE (uniqueid, recording_path) ); CREATE INDEX idx_recorded_at ON recording_metadata(recorded_at); CREATE INDEX idx_agent ON recording_metadata(agent); CREATE INDEX idx_queue ON recording_metadata(queue_name); CREATE INDEX idx_caller ON recording_metadata(caller_id); CREATE INDEX idx_disposition ON recording_metadata(disposition); CREATE INDEX idx_direction ON recording_metadata(direction);

Metama'lumotlarni avtomatik yig'ish skripti

#!/usr/bin/env python3 """ recording_indexer.py — Scans recordings, extracts metadata, populates database. Run every 15 minutes via cron. """ import os import re import wave import subprocess import psycopg2 from datetime import datetime from pathlib import Path DB_CONFIG = { 'host': 'localhost', 'database': 'asterisk', 'user': 'asterisk', 'password': 'your_password' } MONITOR_DIR = '/var/spool/asterisk/monitor' FILENAME_PATTERN = re.compile( r'(\d{8}-\d{6})-(\d+\.\d+)-(\d+)-(\d+)\.wav$' ) def get_wav_duration(filepath): """Get duration in seconds from WAV file.""" try: with wave.open(filepath, 'r') as wf: frames = wf.getnframes() rate = wf.getframerate() return frames / float(rate) except Exception: return None def detect_silence_percentage(filepath): """Detect percentage of silence in recording using sox.""" try: result = subprocess.run( ['sox', filepath, '-n', 'stats'], capture_output=True, text=True, timeout=30 ) # Parse sox stats for RMS level for line in result.stderr.split('\n'): if 'RMS lev dB' in line: rms = float(line.split()[-1]) # Very rough: if RMS < -40dB, significant silence if rms < -40: return 80.0 elif rms < -30: return 50.0 elif rms < -20: return 20.0 return 5.0 except Exception: return None def index_recordings(): conn = psycopg2.connect(**DB_CONFIG) cur = conn.cursor() indexed = 0 for root, dirs, files in os.walk(MONITOR_DIR): for filename in files: if not filename.endswith('.wav'): continue filepath = os.path.join(root, filename) # Skip already indexed cur.execute( "SELECT 1 FROM recording_metadata WHERE recording_path = %s", (filepath,) ) if cur.fetchone(): continue # Extract metadata from filename match = FILENAME_PATTERN.search(filename) if match: timestamp_str, uniqueid, caller, dest = match.groups() recorded_at = datetime.strptime(timestamp_str, '%Y%m%d-%H%M%S') else: # Fallback: use file modification time uniqueid = filename.replace('.wav', '') recorded_at = datetime.fromtimestamp(os.path.getmtime(filepath)) caller = dest = None duration = get_wav_duration(filepath) file_size = os.path.getsize(filepath) silence_pct = detect_silence_percentage(filepath) cur.execute(""" INSERT INTO recording_metadata (uniqueid, recording_path, file_size_bytes, duration_seconds, silence_percentage, caller_id, destination, recorded_at) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ON CONFLICT (uniqueid, recording_path) DO NOTHING """, (uniqueid, filepath, file_size, duration, silence_pct, caller, dest, recorded_at)) indexed += 1 conn.commit() cur.close() conn.close() print(f"Indexed {indexed} new recordings") if __name__ == '__main__': index_recordings()

CDR ma'lumotlari bilan bog'lash

Yozuvlar va CDR o'rtasidagi asosiy join maydoni — uniqueid:

-- Join recordings with CDR for complete call context SELECT r.recording_path, r.duration_seconds, r.silence_percentage, c.src AS caller, c.dst AS destination, c.dcontext AS context, c.billsec AS billable_seconds, c.disposition, c.accountcode, c.userfield AS queue_name FROM recording_metadata r JOIN cdr c ON r.uniqueid = c.uniqueid WHERE r.recorded_at >= CURRENT_DATE - INTERVAL '7 days' ORDER BY r.recorded_at DESC;

4-qadam. Yozuvlar analitikasi uchun asosiy so'rovlar

Yozuvlar CDR ma'lumotlariga bog'langach, kuchli analitik dashboard'lar qurish mumkin.

1-so'rov. Kunlik yozuvlar hajmi va saqlash

-- Daily recording stats: count, total duration, storage used SELECT DATE(recorded_at) AS day, COUNT(*) AS total_recordings, ROUND(SUM(duration_seconds) / 3600.0, 1) AS total_hours, ROUND(SUM(file_size_bytes) / 1073741824.0, 2) AS storage_gb, ROUND(AVG(duration_seconds), 0) AS avg_duration_sec, ROUND(AVG(silence_percentage), 1) AS avg_silence_pct FROM recording_metadata WHERE recorded_at >= CURRENT_DATE - INTERVAL '30 days' GROUP BY DATE(recorded_at) ORDER BY day DESC;

2-so'rov. Operatorlar kesimida yozuvlar tahlili

-- Per-agent recording metrics: identify coaching opportunities SELECT c.dstchannel AS agent_channel, SUBSTRING(c.dstchannel FROM 'SIP/(.+)-') AS agent, COUNT(*) AS calls_recorded, ROUND(AVG(r.duration_seconds), 0) AS avg_duration, ROUND(AVG(r.silence_percentage), 1) AS avg_silence_pct, SUM(CASE WHEN r.duration_seconds < 30 THEN 1 ELSE 0 END) AS short_calls, SUM(CASE WHEN r.silence_percentage > 50 THEN 1 ELSE 0 END) AS high_silence_calls, ROUND(AVG(c.billsec), 0) AS avg_billsec FROM recording_metadata r JOIN cdr c ON r.uniqueid = c.uniqueid WHERE r.recorded_at >= CURRENT_DATE - INTERVAL '7 days' AND c.disposition = 'ANSWERED' GROUP BY c.dstchannel, SUBSTRING(c.dstchannel FROM 'SIP/(.+)-') ORDER BY calls_recorded DESC;

3-so'rov. Yozib olish qamrovi tahlili

-- What percentage of calls are being recorded? -- Identifies gaps in recording coverage SELECT DATE(calldate) AS day, COUNT(*) AS total_calls, COUNT(r.id) AS recorded_calls, ROUND(COUNT(r.id)::DECIMAL / COUNT(*) * 100, 1) AS coverage_pct, COUNT(*) - COUNT(r.id) AS missing_recordings FROM cdr c LEFT JOIN recording_metadata r ON c.uniqueid = r.uniqueid WHERE c.calldate >= CURRENT_DATE - INTERVAL '7 days' AND c.disposition = 'ANSWERED' AND c.billsec > 5 GROUP BY DATE(calldate) ORDER BY day DESC;

4-so'rov. Jimlikni aniqlash — muammoli qo'ng'iroqlarni topish

-- Calls with excessive silence (potential quality issues) -- High silence = hold without music, dead air, or connection problems SELECT r.recorded_at, r.caller_id, r.destination, r.duration_seconds, r.silence_percentage, r.recording_path, c.disposition, c.userfield AS queue FROM recording_metadata r JOIN cdr c ON r.uniqueid = c.uniqueid WHERE r.silence_percentage > 40 AND r.duration_seconds > 60 AND r.recorded_at >= CURRENT_DATE - INTERVAL '7 days' ORDER BY r.silence_percentage DESC LIMIT 20;

Navbatlarda nima sodir bo'layotganini taxmin qilishdan charchadingizmi?

Astervis sizning Asterisk PBX'ingiz uchun 30+ realtime grafik, operator KPI va CRM-integratsiya beradi. On-premise. 5 daqiqada o'rnatiladi. $119/oydan flat operatorlar soni cheklanmagan.

Bepul sinab ko'rish

5-so'rov. Soatlik yozuvlar heatmap'i

-- Recording volume by hour and day of week -- Identifies peak periods and potential capacity issues SELECT EXTRACT(DOW FROM recorded_at) AS day_of_week, EXTRACT(HOUR FROM recorded_at) AS hour, COUNT(*) AS recordings, ROUND(AVG(duration_seconds), 0) AS avg_duration, ROUND(SUM(file_size_bytes) / 1048576.0, 0) AS storage_mb FROM recording_metadata WHERE recorded_at >= CURRENT_DATE - INTERVAL '30 days' GROUP BY EXTRACT(DOW FROM recorded_at), EXTRACT(HOUR FROM recorded_at) ORDER BY day_of_week, hour;

5-qadam. AI asosidagi nutq analitikasi

Zamonaviy yozuvlar analitikasi metama'lumotlar bilan cheklanmaydi. AI nutq analitikasi yozuvlarni avtomatik transkripsiya qilib, mijoz kayfiyati, mavzuni aniqlash va compliance tekshiruvi kabi insight'larni ajratib bera oladi.

Arxitekturaga umumiy nazar

┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Asterisk │────>│ Storage │────>│ Transcribe │────>│ Analyze │ │ MixMonitor │ │ (WAV/Opus) │ │ (Whisper) │ │ (NLP/LLM) │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ ┌──────┴──────┐ │ Dashboard │ │ (Metrics) │ └─────────────┘

1-variant. Whisper'ni o'z serveringizda ishlatish

OpenAI'ning Whisper modeli bepul, ochiq kodli va o'zingizning uskunangizda ishlaydi:

#!/usr/bin/env python3 """ transcribe_recordings.py — Batch transcribe recordings using Whisper. Requires: pip install openai-whisper torch """ import whisper import json import os import psycopg2 from pathlib import Path # Load Whisper model (options: tiny, base, small, medium, large-v3) # 'small' is the best balance of speed and accuracy for telephony model = whisper.load_model("small") DB_CONFIG = { 'host': 'localhost', 'database': 'asterisk', 'user': 'asterisk', 'password': 'your_password' } TRANSCRIPT_DIR = '/var/spool/asterisk/monitor/transcripts' def transcribe_pending(): conn = psycopg2.connect(**DB_CONFIG) cur = conn.cursor() # Get un-transcribed recordings cur.execute(""" SELECT id, recording_path, recorded_at FROM recording_metadata WHERE transcribed = FALSE AND duration_seconds > 10 AND duration_seconds < 1800 ORDER BY recorded_at DESC LIMIT 50 """) for rec_id, rec_path, recorded_at in cur.fetchall(): if not os.path.exists(rec_path): continue try: # Transcribe with Whisper result = model.transcribe( rec_path, language=None, # Auto-detect language task="transcribe", fp16=False # Use fp32 for CPU ) # Save transcript transcript_path = os.path.join( TRANSCRIPT_DIR, recorded_at.strftime('%Y/%m/%d'), f"{os.path.basename(rec_path).replace('.wav', '.json')}" ) os.makedirs(os.path.dirname(transcript_path), exist_ok=True) transcript_data = { 'text': result['text'], 'language': result.get('language', 'unknown'), 'segments': [ { 'start': seg['start'], 'end': seg['end'], 'text': seg['text'] } for seg in result.get('segments', []) ] } with open(transcript_path, 'w') as f: json.dump(transcript_data, f, indent=2) # Update database cur.execute(""" UPDATE recording_metadata SET transcribed = TRUE, transcript_path = %s WHERE id = %s """, (transcript_path, rec_id)) conn.commit() print(f"Transcribed: {os.path.basename(rec_path)} " f"({result.get('language', '?')})") except Exception as e: print(f"Error transcribing {rec_path}: {e}") continue cur.close() conn.close() if __name__ == '__main__': transcribe_pending()

Whisper uchun uskuna talablari

ModelVRAMCPU: audio daqiqasiga vaqtGPU: audio daqiqasiga vaqtAniqlik
tiny~1 GB~10 soniya~1 soniyaKalit so'z qidirish uchun yetarli
base~1 GB~15 soniya~2 soniyaAnalitika uchun maqbul
small~2 GB~30 soniya~3 soniyaTelefoniya uchun tavsiya etiladi
medium~5 GB~60 soniya~5 soniyaYuqori aniqlik
large-v3~10 GB~120 soniya~8 soniyaEng yuqori aniqlik

Kuniga o'rtacha 5 daqiqalik 300 ta yozuvni qayta ishlaydigan 50 operatorli call-markaz uchun GPU'dagi small modeli butun kunlik yozuvlarni taxminan 75 daqiqada ko'rib chiqadi.

2-variant. Bulutli transkripsiya API'si

Boshqariladigan xizmatni afzal ko'radigan jamoalar uchun:

# Using OpenAI Whisper API (cloud) import openai client = openai.OpenAI(api_key="your-api-key") def transcribe_cloud(audio_path): with open(audio_path, "rb") as audio_file: transcript = client.audio.transcriptions.create( model="whisper-1", file=audio_file, response_format="verbose_json", timestamp_granularities=["segment"] ) return transcript

Bulutli API taxminan audio daqiqasiga $0.006 turadi. Kuniga 300 qo'ng'iroq × 5 daqiqa hisobida bu kuniga $9, ya'ni oyiga ~$270.

Kalit so'zlar va mavzularni aniqlash

Transkriptlar tayyor bo'lgach, kalit so'zlar va mavzularni AI'siz ham topish mumkin:

#!/usr/bin/env python3 """ keyword_analyzer.py — Detect keywords and topics in call transcripts. """ import json import re from collections import Counter # Define keyword categories relevant to your business KEYWORD_CATEGORIES = { 'complaint': [ 'complaint', 'unhappy', 'dissatisfied', 'terrible', 'worst', 'cancel', 'refund', 'manager', 'supervisor', 'unacceptable' ], 'upsell_opportunity': [ 'upgrade', 'additional', 'more features', 'enterprise', 'premium', 'advanced', 'expand', 'grow', 'scale' ], 'technical_issue': [ 'not working', 'broken', 'error', 'bug', 'crash', 'down', 'outage', 'slow', 'timeout', 'failed' ], 'positive': [ 'thank you', 'excellent', 'great', 'wonderful', 'perfect', 'appreciate', 'helpful', 'resolved', 'solved', 'happy' ], 'compliance_risk': [ 'guarantee', 'promise', 'definitely', 'always', 'never', 'lawsuit', 'legal', 'attorney', 'sue' ] } def analyze_transcript(transcript_path): with open(transcript_path) as f: data = json.load(f) text = data['text'].lower() results = {} for category, keywords in KEYWORD_CATEGORIES.items(): found = [] for keyword in keywords: count = len(re.findall(r'\b' + re.escape(keyword) + r'\b', text)) if count > 0: found.append({'keyword': keyword, 'count': count}) results[category] = { 'matches': found, 'total_hits': sum(m['count'] for m in found), 'flagged': len(found) > 0 } return results

Segmentlar bo'yicha kayfiyat dinamikasi

# Simple sentiment scoring per transcript segment # For production: use a fine-tuned model or LLM API from textblob import TextBlob def segment_sentiment(transcript_path): """Analyze sentiment across call segments to detect escalation patterns.""" with open(transcript_path) as f: data = json.load(f) timeline = [] for segment in data.get('segments', []): blob = TextBlob(segment['text']) timeline.append({ 'start': segment['start'], 'end': segment['end'], 'text': segment['text'], 'polarity': round(blob.sentiment.polarity, 2), # -1 to 1 'subjectivity': round(blob.sentiment.subjectivity, 2) # 0 to 1 }) # Detect escalation: sentiment dropping over time if len(timeline) > 4: first_quarter = sum(s['polarity'] for s in timeline[:len(timeline)//4]) last_quarter = sum(s['polarity'] for s in timeline[-len(timeline)//4:]) escalation = first_quarter - last_quarter > 0.5 else: escalation = False return { 'segments': timeline, 'avg_polarity': round(sum(s['polarity'] for s in timeline) / max(len(timeline), 1), 2), 'escalation_detected': escalation }

6-qadam. Compliance va saqlash muddatlari

Qo'ng'iroqlarni yozib olish qoidalari yurisdiksiyalar bo'yicha jiddiy farq qiladi. Bu talablarga rioya qilmaslik jarimalar va yuridik javobgarlikka olib kelishi mumkin.

Yozib olishga rozilik modellari

ModelTalabYurisdiksiyalar
Bir tomon roziligiSuhbatdagi bir kishi bilishi yetarliAQSh (federal daraja), Buyuk Britaniya, Yevropa Ittifoqining ko'p qismi
Ikki/barcha tomon roziligiSuhbatdagi hamma bilishi shartKaliforniya, Florida, Germaniya, ba'zi Yevropa Ittifoqi davlatlari
Rozilik talab qilinmaydiIshga oid qo'ng'iroqlar istisnoBa'zi B2B holatlar

Rozilik e'lonini qanday qo'shish kerak

; extensions.conf — Play recording notification before connecting [inbound-queue] exten => s,1,Answer() same => n,Playback(this-call-may-be-recorded) same => n,Wait(0.5) same => n,Macro(record-call) same => n,Queue(support,t,,,180) same => n,Hangup()

Avtomatik saqlash siyosati

#!/bin/bash # recording-retention.sh — Enforce data retention policies # Run weekly via cron MONITOR_DIR="/var/spool/asterisk/monitor" TRANSCRIPT_DIR="$MONITOR_DIR/transcripts" # Retention periods (adjust per your compliance requirements) RECORDING_RETENTION_DAYS=365 # Keep recordings for 1 year TRANSCRIPT_RETENTION_DAYS=730 # Keep transcripts for 2 years COMPRESSED_RETENTION_DAYS=730 # Keep compressed archives for 2 years echo "$(date): Starting retention cleanup" # Delete original WAV files older than retention period find "$MONITOR_DIR" -name "*.wav" -mtime +$RECORDING_RETENTION_DAYS \ -not -path "*/compressed/*" -delete -print | wc -l | \ xargs -I {} echo "Deleted {} expired WAV files" # Delete compressed files older than retention period find "$MONITOR_DIR/compressed" -name "*.opus" \ -mtime +$COMPRESSED_RETENTION_DAYS -delete -print | wc -l | \ xargs -I {} echo "Deleted {} expired compressed files" # Delete transcripts older than retention period find "$TRANSCRIPT_DIR" -name "*.json" \ -mtime +$TRANSCRIPT_RETENTION_DAYS -delete -print | wc -l | \ xargs -I {} echo "Deleted {} expired transcripts" # Clean empty directories find "$MONITOR_DIR" -type d -empty -delete echo "$(date): Retention cleanup complete"

GDPR va ma'lumot subyektlarining so'rovlari

GDPR talablariga javob berish uchun sizda muayyan qo'ng'iroq qiluvchiga tegishli barcha yozuvlarni topish va o'chirish imkoniyati bo'lishi kerak:

-- Find all recordings for a specific caller (data subject request) SELECT recording_path, transcript_path, recorded_at, duration_seconds, destination FROM recording_metadata WHERE caller_id = '2125551234' ORDER BY recorded_at DESC; -- Delete all data for a specific caller (right to erasure) -- Step 1: Get file paths for physical deletion SELECT recording_path, transcript_path FROM recording_metadata WHERE caller_id = '2125551234'; -- Step 2: Delete database records DELETE FROM recording_metadata WHERE caller_id = '2125551234';

7-qadam. Dashboard qurish

Yozuvlar analitikasi dashboard'i xulosalarni o'zi ko'rsatishi kerak — supervayzerni har bir yozuvni qo'lda qayta tinglashga majburlamasdan.

Dashboard karkasi: uch daraja

1-daraja — real vaqtdagi wallboard (bir qarashda tushunarli):

  • Ayni damda ketayotgan yozuvlar
  • Bugungi yozuvlar soni va reja solishtiruvi
  • Saqlash hajmining to'lganlik foizi
  • Yozib olishdagi nosozliklar haqida ogohlantirishlar

2-daraja — kundalik operatsion nazorat (supervayzerlar uchun):

  • Yozib olish qamrovi foizi (barcha qo'ng'iroqlar yozilyaptimi?)
  • O'rtacha qo'ng'iroq davomiyligi dinamikasi
  • Jimlik ulushining taqsimoti
  • Ko'rib chiqish uchun jimligi yuqori qo'ng'iroqlar belgisi
  • Kalit so'z detektori belgilagan qo'ng'iroqlar

3-daraja — strategik analitika (haftalik/oylik):

  • Yozuvlar hajmi trendlari
  • Saqlash o'sishi prognozi
  • Transkriptlardan insight'lar: eng ko'p uchragan mavzular, kayfiyat dinamikasi
  • Operatorlarni o'qitish nuqtalari (ko'p jimlik, qisqa qo'ng'iroqlar)
  • Compliance auditi: qamrovdagi bo'shliqlar, rozilik e'lonini tekshirish

Kuzatib boriladigan asosiy metrikalar

MetrikaFormulaMaqsadNega muhim
Yozib olish qamroviYozilgan qo'ng'iroqlar / Javob berilgan barcha qo'ng'iroqlar × 100>98%Qo'ng'iroqlar yozilmasa — compliance riski
O'rtacha yozuv davomiyligiYozuvlarning umumiy soniyasi / Yozuvlar soniBiznesga bog'liqTrend o'zgarishi jarayondagi muammodan darak beradi
Jimlik ulushiJimlik soniyalari / Umumiy davomiylik × 100<20%Ko'p jimlik = kutish vaqti, "o'lik efir"
Saqlash o'sish tezligiKuniga qo'shiladigan GB2 barobar zaxira bilan rejalangDisk to'lib qolishining oldini oladi
Transkripsiya navbatiTranskripsiya qilinmagan / Barcha yozuvlar<5%Analitikaning dolzarbligini ta'minlaydi
Salbiy kayfiyat ulushiSalbiy qo'ng'iroqlar / Transkripsiya qilinganlar × 100<15%Mijoz mamnunligi indikatori
Compliance belgilari ulushiBelgilangan qo'ng'iroqlar / Transkripsiya qilinganlar × 100<2%Risklarni boshqarish

Solishtiruv: yozuvlar analitikasiga yondashuvlar

XususiyatO'z skriptlaringizQueueMetricsCallCabinetAstervis
Joriy etish mehnatiYuqori (haftalar)O'rtacha (kunlar)Past (soatlar)Past (daqiqalar)
Yozuvlarni tinglashFayllarga qo'lda kirishIchki pleyerBulutli pleyerIchki pleyer
CDR bilan bog'lanishO'z SQL'ingizAvtomatikAvtomatikAvtomatik
Raqam/sana bo'yicha qidiruvSQL so'rovlarGUI qidiruviGUI qidiruviBir zumda qidiruv
Nutq analitikasiO'zingiz yozasizYo'qAI asosida ($$$)Tez orada
Jimlikni aniqlashO'z skriptlaringizYo'qBorBor
Compliance vositalariQo'ldaAsosiyTo'liq to'plamIchki saqlash siyosatlari
Operatorlarni baholashYo'qQo'lda QA formalariAI baholashAvtomatik KPI'lar
NarxiBepul + sizning vaqtingizCHF 8/agent/oyNarx so'rov bo'yicha$119/oydan
Self-hostedHaHaFaqat bulutHa
Real vaqtdagi dashboardO'zingiz yozasizAsosiyHa30+ grafik

Tez start uchun cheklist

Noldan ishlaydigan qo'ng'iroq yozuvlari analitikasigacha bo'lgan yo'l:

  • 1-qadam: yozib olishni yoqing — dialplan'ga MixMonitor'ni tuzilgan fayl nomlari bilan qo'shing
  • 2-qadam: saqlashni tashkil qiling — sana bo'yicha kataloglar yarating, hajmni rejalang
  • 3-qadam: CDR bilan bog'langCDR(recordingfile) to'lib turishiga ishonch hosil qiling, metama'lumotlar jadvalini yarating
  • 4-qadam: yozuvlarni indekslang — indekslash skriptini cron orqali har 15 daqiqada ishga tushiring
  • 5-qadam: eski fayllarni siqing — kunlik siqish cron vazifasini sozlang
  • 6-qadam: oddiy dashboard yig'ing — qamrov va davomiylik so'rovlaridan boshlang
  • 7-qadam: transkripsiyani qo'shing — Whisper'ni o'rnating, paketli transkripsiyani ishga tushiring
  • 8-qadam: kalit so'zlarni aniqlashni sozlang — kategoriyalarni belgilang, transkriptlarni avtomatik skanerlang
  • 9-qadam: saqlash siyosatini belgilang — compliance talablaringizga mos avtomatik tozalashni sozlang
  • 10-qadam: ko'rib chiqing va yaxshilang — har hafta dashboard metrikalarini tahlil qiling, chegaralarni moslang

Keyingi qadam

Qo'ng'iroq yozuvlari analitikasini noldan qurish kuchli natija beradi, lekin ko'p vaqt oladi. Skriptlarni qo'llab-quvvatlash, saqlashni boshqarish, transkripsiya pipeline'larini ishlab turishga majbur qilish va dashboard'lar qurish kerak — bularning barchasi call-markazni boshqarish bilan bir vaqtda.

Astervis og'ir yukni o'z zimmasiga oladi. Bitta buyruq bilan o'rnating va darhol 30+ analitik grafik, CDR bilan bog'langan qo'ng'iroq yozuvlarini tinglash, operatorlar samaradorligini kuzatish va navbatlarni real vaqtda monitoring qilish imkoniyatiga ega bo'ling — bitta ham SQL so'rov yozmasdan.

14 kunlik bepul sinov bilan boshlang: astervis.io


Asterisk analitikasi bo'yicha yana qo'llanmalar kerakmi? Asterisk navbatlarini real vaqtda monitoring qilish, CDR hisobotining eng yaxshi amaliyotlari va operatorlar samaradorligini kuzatish haqidagi maqolalarimizni o'qing.

Taxmin qilishni bas qiling. Ko'rishni boshlang.

Asterisk call-markazingizning haqiqiy ko'rinishi: navbatlardagi kutish vaqti, operatorlar faolligi, trunk yuklamasi va 30+ grafik. Sizning serveringizda on-premise. 5 daqiqada o'rnatish. Kartasiz.

$119/oydan flat. Operatorlar soni cheklanmagan. 14 kunlik triаl.

Ulashish