Я пытаюсь преобразовать файлы .wav в текст, чтобы мы могли выполнить анализ речи для вызовов, на которые ответила моя компания. Я получил работающий прототип, но он медленный и занимает много времени, чтобы просто расшифровать 100 файлов. Мне нужно иметь возможность делать около 30 тысяч файлов в день.
Вот мой код до сих пор. Это пошагово, то есть пользователь должен запускаться один за другим.
Первый шаг — получить файл с сервера S3.
S3.php
<?php
require 'aws-autoloader.php';
include 'db.php'; // my DB connection file
set_time_limit(0);
ignore_user_abort(true);
ini_set('max_execution_time', 0); // setting timer to so the script does not time out
$credentials = new Aws\Credentials\Credentials('', '');
$s3Client = new Aws\S3\S3Client([ // S3 client connection
'version' => 'latest',
'region' => 'us-east-1',
'credentials' => $credentials
//'debug' => true
]);
echo "<br>";
$objects = $s3Client->getIterator('ListObjects', array(
"Bucket" => 'bucker_name',
"Prefix" => "folder1/folder2/folder3/2017/10/05/"));
$i = 0;
foreach ($objects as $object) {
try {
if ($i == 140) break; // This is the counter I set to get only 140 files
if ($object['Size'] > 482000 and $object['Size'] < 2750000) { // get only objects that are not too small nor too big or consider it file filerting
echo $object['Key'] . "<br>";
$i++;
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => 'bucket_name',
'Key' => $object['Key']
]);
// Create a signed URL from a completely custom HTTP request that
// will last for 10 minutes from the current time
$signedUrl = $s3Client->createPresignedRequest($cmd, '+10 minutes');
ob_start();
echo $url = (string)$signedUrl->getUri();
ob_end_flush();
ob_flush();
flush();
$filename = parse_url($url, PHP_URL_PATH);
$arr = explode("_", basename($filename));
$filename = $arr[0] . ".wav";
file_put_contents('uploads/' . basename($filename), fopen($url, 'r')); // Storing the files in uploads folder on my Linux server
$sql = "INSERT INTO `audioFiles` (`audioFile`) VALUES ('" . basename($filename) . "')"; // Inserting the file name into DB to keep track of it
$STH = $DBH->prepare($sql);
$STH->execute();
}
//print_r($object);
} catch (Exception $e) {
print_r($e);
}
}
Как только файлы загружены, мне нужно разделить запись на левую и правую и использовать первые 5 секунд с правой стороны. Я делаю это потому, что дорого переписывать весь вызов, и это скорее инициализирующее приложение, которое должно масштабироваться до тысяч файлов, прежде чем мы сможем рационализировать это для всей продолжительности каждого файла.
Вот часть скрипта, используемая для разделения и извлечения первых 5 секунд. Я получаю имена файлов из БД, у которых маркер равен 0, и для разделения, а затем обновляю маркер файла БД, используя новое имя и маркер как 1.
Split.php
$sql = "SELECT audioFile FROM audioFiles WHERE split = 0"; // SQL to get file names
$sql_update = "UPDATE audioFiles SET split = 1 WHERE audioFile IN ("; // SQL to update split files
.
.
while ($fileName = $STH->fetch()) {
echo $output = shell_exec("sox --i " . $location . " | grep Channels | sed 's/^.*: //'"); // to check if the file has stereo or mono recording
if ($output == 2) {
$left = substr($location, 0, $extension_pos) . '.CALLER' . substr($location, $extension_pos);
$right = substr($location, 0, $extension_pos) . '.AGENT' . substr($location, $extension_pos);
$ap = substr($location, 0, $extension_pos) . '.AGENT.AP' . substr($location, $extension_pos);
exec("sox $location $left remix 1 ");
exec("sox $location $right remix 2 ");
exec("sox $location $ap trim 0 5");
$sql_update .= "'" . $fileName[0] . "',";
$sql_update_agentTranscript = "UPDATE audioFiles SET agentFile ='" . $right . "', agentAP ='".$ap ."' WHERE audioFile ='" . $fileName[0] . "'";
$STH1 = $DBH->prepare($sql_update_agentTranscript);
$STH1->execute();
} else if ($output == 1) {
$right = substr($location, 0, $extension_pos) . '.AGENT' . substr($location, $extension_pos);
$ap = substr($location, 0, $extension_pos) . '.AGENT.AP' . substr($location, $extension_pos);
exec("cp $location $right");
exec("sox $location $ap trim 0 5");
$sql_update .= "'" . $fileName[0] . "',";
$sql_update_agentTranscript = "UPDATE audioFiles SET agentFile ='" . $right . "', agentAP ='".$ap ."' WHERE audioFile ='" . $fileName[0] . "'";
$STH1 = $DBH->prepare($sql_update_agentTranscript);
$STH1->execute();
} else {
echo "Something is wrong. The file did not have 1 or 2 channel or code is wrong - ".$fileName[0];
echo "<br>";
$ap = substr($location, 0, $extension_pos) . '.AGENT.AP' . substr($location, $extension_pos);
}
$sql_update = substr($sql_update, 0, -1);
$sql_update .= ")";error_log($sql_update, 0);
$STH = $DBH->prepare($sql_update);
$STH->execute();
Вот сценарий, используемый для преобразования 5-секундных файлов в текст.
IBM.php
<?php
.
//get file name from DB with marker set as 1 from previous script.
$url = 'https://stream.watsonplatform.net/speech-to-text/api/v1/recognize?model=en-US_NarrowbandModel&profanity_filter=false';
$headers = array(
"Content-Type: audio/wav",
"Transfer-Encoding: chunked");
.
if($STH->rowCount() > 0) {
while ($fileName = $STH->fetch()) {
$file = fopen($fileName[0], 'r');
$size = filesize($fileName[0]);
$fileData = fread($file, $size);
// CURL start to send via IBM API and conver it.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fileData);
curl_setopt($ch, CURLOPT_INFILE, $file);
curl_setopt($ch, CURLOPT_INFILESIZE, $size);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$executed = curl_exec($ch);
curl_close($ch);
$result = json_decode($executed);
$match = "thank you for calling"; // The text to see if they are present in the converted text
$transcript = $result->results[0]->alternatives[0]->transcript;
if(strpos($transcript,$match) !== false){
//Update DB with STH1->execute() to say that matching text is found.
} else {
//Update DB with STH2->execute() to say that matching text is not found.
}
}
}
else{
echo "No more files to convert.";
}
?>
Выше можно использовать для преобразования речи в текст с использованием IBM Watson. Просто добавьте его, если кто-то захочет его использовать.
Весь трехэтапный процесс, как я предполагаю, будет работать для сотен вызовов, но не будет работать или будет слишком дорогим для выполнения тысяч вызовов.
Шаги могут быть перечислены следующим образом.
Мне нужна помощь, чтобы оптимизировать этот поток и сделать его быстрее, чем сейчас. Я надеялся, что будет способ отправить файл из S3 в IBM Watson напрямую в виде потока с 5-секундным ограничением времени для каждого файла. Я думаю, что это возможно, но я понятия не имею, как это сделать.
Нужно ли воссоздавать его полностью? если так, какой другой вариант есть?
Любые предложения или идеи помогут.
Ps — прошу прощения за отступ кода
Задача ещё не решена.
Других решений пока нет …