Voice Transcription System

projects.astcrm.com/voiceTranscription

Phase 1 — Audio Submission  ·  api.php
Source
External CRM / PBX
POST audioID · voicefileURL · audioSource
Step 1
Validate Input
Check audioID, voicefileURL, audioSource (PBXdemo / CCDdemo / OmniCoredemo)
Step 2
Download Audio File
cURL download from voicefileURL → temp file
Decision — File Format
GSM or WAV?
GSM
Convert → WAV
sox -t gsm -r 8000 -c 1
Save to WAV/
WAV
Move to WAV/
audioID_timestamp.wav
No conversion needed
Step 3 — Database
INSERT voice_records
audioID · audioSource · voicefileURL · wavFile · status = pending
Step 4
Upload to Callmetrik API
POST api.callmetrik.com/v1.3/…/13
Params: audioID · audioSource (mapped)
Auth: PDAI-API-Token

PBXdemo → pbx  |  CCDdemo → ccd  |  OmniCoredemo → omnichannel
Response
Return Callmetrik Response
Raw JSON forwarded back to caller
Phase 2 — Result Webhook  ·  voiceTranscriptionWebhook.php
Source
Callmetrik API Callback
POST raw JSON — success or failure (e.g. NO_SPEECH_DETECTED)
Step 1
Parse JSON Body
Extract audioID from results[] — regardless of success/failure flag
Step 2
Save JSON Log
json_logs/voice_{datetime}_{uniqid}.json
Build full URL: https://projects.astcrm.com/…/json_logs/…
Step 3 — Database
Lookup voice_records
SELECT by audioID → get id, audioSource
Step 4 — Database
UPDATE voice_records
json_log · json_url · status = completed
Decision — audioSource
Which Internal Server?
CCDdemo
POST → 10.0.6.250/astVlogger/analysis_json.php
id = audioID  ·  json_url = full HTTPS URL
PBXdemo
POST → 10.0.10.162/astVlogger/analysis_json.php
id = audioID  ·  json_url = full HTTPS URL
OmniCoredemo
POST → demo.astcrm.com/staging/omnicore/…
id = audioID  ·  json_url = full HTTPS URL
Step 5 — Database
Save forward_response
Store raw response from analysis_json.php into voice_records

Database · voiceTranscriptionDB.voice_records

Column Type Description
idINT AUTO_INCREMENTPrimary key
audioIDVARCHAR(100)ID from the source CRM/PBX system
audioSourceENUMPBXdemo · CCDdemo · OmniCoredemo
voicefileURLTEXTOriginal download URL
wavFileVARCHAR(255)Saved filename in WAV/ folder
json_logVARCHAR(255)Callmetrik result filename in json_logs/
json_urlTEXTFull HTTPS URL to the JSON result
forward_responseTEXTResponse from internal analysis_json.php
statusENUMpendingcompleted / failed
created_atDATETIMERecord creation time
updated_atDATETIMEAuto-updated on any change

API Documentation
POST https://projects.astcrm.com/voiceTranscription/api.php
Submit an audio file for transcription and analysis. Downloads the file, converts GSM to WAV if needed, saves to WAV/, then uploads to Callmetrik for processing.
ParameterTypeDescription
audioIDrequired string Unique identifier for the audio file from your system
voicefileURLrequired string (URL) Publicly accessible URL to the audio file (.wav or .gsm)
audioSourcerequired enum Source system identifier:
PBXdemo → sends as pbx to Callmetrik
CCDdemo → sends as ccd to Callmetrik
OmniCoredemo → sends as omnichannel to Callmetrik
api_keyrequired string API key for the given audioSource. Can be passed as:
— POST body field: api_key=your_key
— HTTP header: X-API-Key: your_key
Manage keys at Admin Panel
curl -X POST https://projects.astcrm.com/voiceTranscription/api.php \ -H "X-API-Key: your_api_key_here" \ -d "audioID=4430" \ -d "voicefileURL=https://example.com/recordings/call-4430.wav" \ -d "audioSource=PBXdemo"
<?php $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => 'https://projects.astcrm.com/voiceTranscription/api.php', CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'audioID' => '4430', 'voicefileURL' => 'https://example.com/recordings/call-4430.wav', 'audioSource' => 'PBXdemo', ]), CURLOPT_HTTPHEADER => [ 'X-API-Key: your_api_key_here', ], ]); $response = curl_exec($curl); curl_close($curl); $data = json_decode($response, true); print_r($data);
import requests url = 'https://projects.astcrm.com/voiceTranscription/api.php' headers = { 'X-API-Key': 'your_api_key_here' } data = { 'audioID': '4430', 'voicefileURL': 'https://example.com/recordings/call-4430.wav', 'audioSource': 'PBXdemo' } response = requests.post(url, data=data, headers=headers) print(response.json())
const formData = new FormData(); formData.append('audioID', '4430'); formData.append('voicefileURL', 'https://example.com/recordings/call-4430.wav'); formData.append('audioSource', 'PBXdemo'); const response = await fetch( 'https://projects.astcrm.com/voiceTranscription/api.php', { method: 'POST', headers: { 'X-API-Key': 'your_api_key_here' }, body: formData, } ); const data = await response.json(); console.log(data);
const https = require('https'); const querystring = require('querystring'); const postData = querystring.stringify({ audioID: '4430', voicefileURL: 'https://example.com/recordings/call-4430.wav', audioSource: 'PBXdemo', }); const options = { hostname: 'projects.astcrm.com', path: '/voiceTranscription/api.php', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData), 'X-API-Key': 'your_api_key_here', }, }; const req = https.request(options, (res) => { let body = ''; res.on('data', (chunk) => body += chunk); res.on('end', () => console.log(JSON.parse(body))); }); req.write(postData); req.end();
Success Response (200)
{ "success": true, "message": "Successfully processed 1 audio(s)", "results": [ { "audioID": "4430", "transcription": "Hello, how can I help you...", "language": "en" } ] }
Failure Response (from Callmetrik)
{ "success": false, "message": "processed 0 audio(s), failed 1", "error_code": "NO_SPEECH_DETECTED", "results": [ { "audioID": "4430", "message": "No speech detected in the audio file", "error_code": "NO_SPEECH_DETECTED" } ] }
405Method Not Allowed — must use POST
400Missing required parameter (audioID / voicefileURL / audioSource)
400Invalid audioSource value
401Missing api_key — not provided in body or header
403Invalid or inactive API key for the given audioSource
502Failed to download audio file from voicefileURL
500GSM → WAV conversion failed (sox error)
502Failed to reach Callmetrik API
POST https://projects.astcrm.com/voiceTranscription/voiceTranscriptionWebhook.php
Webhook endpoint called by Callmetrik when analysis is complete. Saves the result JSON, updates the database, and forwards the result to the appropriate internal server based on audioSource.
ParameterTypeDescription
Bodyrequired JSON (raw) Raw JSON body sent by Callmetrik. Must contain a results[] array with audioID field.
curl -X POST https://projects.astcrm.com/voiceTranscription/voiceTranscriptionWebhook.php \ -H "Content-Type: application/json" \ -d '{ "success": true, "results": [{"audioID": "4430", "transcription": "Hello..."}] }'
<?php $payload = json_encode([ 'success' => true, 'results' => [ ['audioID' => '4430', 'transcription' => 'Hello...'] ] ]); $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => 'https://projects.astcrm.com/voiceTranscription/voiceTranscriptionWebhook.php', CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], ]); $response = curl_exec($curl); curl_close($curl); print_r(json_decode($response, true));
import requests url = 'https://projects.astcrm.com/voiceTranscription/voiceTranscriptionWebhook.php' payload = { 'success': True, 'results': [ {'audioID': '4430', 'transcription': 'Hello...'} ] } response = requests.post(url, json=payload) print(response.json())
const response = await fetch( 'https://projects.astcrm.com/voiceTranscription/voiceTranscriptionWebhook.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ success: true, results: [{ audioID: '4430', transcription: 'Hello...' }] }), } ); const data = await response.json(); console.log(data);
const https = require('https'); const payload = JSON.stringify({ success: true, results: [{ audioID: '4430', transcription: 'Hello...' }] }); const options = { hostname: 'projects.astcrm.com', path: '/voiceTranscription/voiceTranscriptionWebhook.php', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload), }, }; const req = https.request(options, (res) => { let body = ''; res.on('data', (chunk) => body += chunk); res.on('end', () => console.log(JSON.parse(body))); }); req.write(payload); req.end();
Example Payload from Callmetrik (Success)
{ "success": true, "message": "Successfully processed 1 audio(s)", "results": [ { "audioID": "4430", "transcription": "Hello, how can I help you today...", "language": "en", "duration": 42.3 } ] }
Example Payload from Callmetrik (Failure)
{ "success": false, "message": "Successfully processed 0 audio(s), failed 1", "error_code": "NO_SPEECH_DETECTED", "results": [ { "audioID": "4430", "message": "No speech detected in the audio file", "error_code": "NO_SPEECH_DETECTED" } ] }
Forwarded to Internal Server (POST body)
id=4430&json_url=https://projects.astcrm.com/voiceTranscription/json_logs/voice_20260331_120000_abc123.json
Webhook Response
{ "status": "success", "audioID": "4430", "audioSource": "PBXdemo", "filename": "voice_20260331_120000_abc123.json", "json_url": "https://projects.astcrm.com/voiceTranscription/json_logs/voice_20260331_120000_abc123.json", "forward_url": "http://10.0.10.162/astVlogger/analysis_json.php", "forward_status": 200, "forward_response": "{\"status\":true,\"message\":\"Successfully updated\"}", "forward_error": null }
400Empty request body
200Saved but no audioID found in results[]
200No DB record found for audioID (not forwarded)
200OmniCoredemo — forwarded to demo.astcrm.com
POST Internal Forwarding — analysis_json.php
After receiving the Callmetrik result, the webhook forwards to the correct internal server based on audioSource.
audioSourceInternal EndpointPOST Fields
CCDdemo http://10.0.6.250/astVlogger/analysis_json.php id, json_url
PBXdemo http://10.0.10.162/astVlogger/analysis_json.php id, json_url
OmniCoredemo https://demo.astcrm.com/staging/omnicore/voiceTranscriptionWebhook.php id, json_url

Admin Panel
📊
Dashboard
dashboard.php
Analytics overview. Requires login.
  • Summary cards — today / week / month / all-time
  • Status breakdown doughnut chart
  • 14-day daily activity bar chart
  • Per-source request stats table
  • 5 most recent records
📋
Request Logs
logs.php
Full request log viewer. Requires login.
  • Filter by source, status, date range, audioID
  • Expand row → 4 panels: Request · Callmetrik Upload · Analysis Result · Forward Response
  • Inline WAV audio player
  • Retry forward to internal server (AJAX)
  • Auto-refresh every 30s toggle
  • Export filtered results to CSV
🔑
API Key Management
manage_keys.php
Manage API keys per audioSource. Requires login.
  • Add new audioSource → auto-generates 64-char key
  • Regenerate or disable/enable any key
  • Update forward URL per source
  • Per-key stats: total, success, failed, last used
🩺
System Health
health.php
Live system status check. Requires login.
  • Ping Callmetrik API with response time
  • Ping all active forward URLs
  • Pending / stuck records queue status
  • WAV + JSON storage size & disk free space
🗂️
File Manager
files.php
Manage stored files. Requires login.
  • Browse WAV files with inline audio player
  • Browse JSON logs with inline preview
  • Delete individual files
  • Bulk delete selected files
  • Delete all files in one click
  • Storage summary cards
✉️
Email Alerts
mailer.php (internal)
Automatic email alerts to s.veerdev@asttecs.com.
  • Callmetrik returns success: false (e.g. NO_SPEECH_DETECTED)
  • Forward URL returns non-2xx or is unreachable
  • Sent via SMTP: mailasttecs.com:465 (SSL)
AUTH https://projects.astcrm.com/voiceTranscription/login.php
FieldValue
Usernameadmin
SessionPHP session cookie — expires on browser close. Logout via navbar.