|
|
Рассказы в mp3
это перепост заметки, оригинал находится на моем сайте: https://lleo.me/dnevnik/2021/11/03 На спор со знакомым грелочником смастерил вчера скриптик для перегонки рассказов в mp3. Использовал речевой синтезатор Яндекса. Рассказы бил на фразы и собирал в порции по 1000 букв, потому что там такое ограничение. Рассказов больше 200, за ночь все было готово. Думал, не хватит моего ключа API - помнится, там было какое-то ограничение, не более 1000 обращений в месяц или что-то вроде того. Но ключ выдержал. Яндекс, дай мне неограниченный ключ для подобных некоммерческих экспериментов? Рассказы в озвучке выглядят достаточно пристойно: Группа 1: https://disk.yandex.ru/d/oB-3_cFYsTwNnQ Группа 2: https://disk.yandex.ru/d/1k94b3IgyuxDrQ Группа 3: https://disk.yandex.ru/d/rtGvzbFyCFrMnw Группа 4: https://disk.yandex.ru/d/9rDrE6uprKdd5Q Группа 5: https://disk.yandex.ru/d/wRp8nsbqIGw99g Даже "Гуси-лебеди" из второй группы. Нет, не мой. Я в этот раз не участвую - прорыв трубы и ремонт не оставил времени. Собственно, пишу я это пост лишь для того, чтобы выложить сюда код, который превращает всю Грелку в mp3 - он совсеми коротенький. Может, вам кому пригодится, да и мне полезно такие вещи хранить в дневнике, а то потеряется, а где потом искать, если понадобится что-то в звук перегнать:
<?php
#!/usr/bin/php
<?php
// впишите ваш ключ речевого API Яндекса: $API="ae31d6fb-f342-4501-8648-7e4bea9dedb4"; // титульная страница нынешней Грелки: $GRELKA='http://www.leningrad.su/makod/texts/k211_competition.htm';
$list='/tmp/grelka.htm'; if(!is_file($list)) file_put_contents($list,file_get_contents($GRELKA)); $s=file_get_contents($list); $s=wu($s);
$m=explode("<p><center><h4>",$s);
foreach($m as $num=>$l) {
if( preg_match_all("/(\d+)\. \(\d+\) <a href=\"(.+?)\">(.+?)<\/a>/s",$l,$e) ) { $gd="Группа ".$num; if(!is_dir($gd)) mkdir($gd); echo "\n\n === ".$gd;
foreach($e[0] as $i=>$l) { $nm=$e[1][$i]; $url="http://www.leningrad.su".$e[2][$i]; $name=trim($e[3][$i]); $to=$gd."/".sprintf("%02d",$nm)." ".$name.".txt";
echo "\n $url [$name] -> ".$to;
if(is_file($to)) $txt=file_get_contents($to); else { $txt=file_get_contents($url); $txt=wu(ochictka($txt)); file_put_contents($to,$txt); }
say_text($gd."/".sprintf("%02d",$nm)." ".$name,$txt); } }
}
function wu($s) { $s=strtr($s,chr(152),'@'); return(iconv("windows-1251","utf-8//IGNORE",$s)); } function uw($s) { return(iconv("utf-8","windows-1251//IGNORE",$s)); }
function ochictka($s) { $s=str_replace("\r",'',$s); $s=str_replace(' ',' ',$s); $s=str_replace('"','"',$s); $s=str_ireplace('<p align="justify">','<p>',$s); $s=str_ireplace('</p>','',$s); $s=str_ireplace('<p>','',$s); if(!preg_match("/<hr>.+?<hr>(.+?)<hr>/s",$s,$m)) die("No body!"); $s=$m[1]; if(!preg_match("/<h3><center><b>(.+?)<\/b><\/h3><\/center>(.+?)$/s",$s,$m)) die("No Header!"); $head=$m[1]; $s=$m[2]; return $head."\n\n".$s; }
function say($text,$out) { // собственно процедура озвучки: даем ей текст и имя файла if(empty($text)) return; $url="https://tts.voicetech.yandex.net/generate"; $ch = curl_init($url); curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3'); curl_setopt ($ch, CURLOPT_POST, 1); curl_setopt ($ch, CURLOPT_POSTFIELDS, "format=mp3" // mp3 — MPEG-1 Layer 3; wav — PCM; opus — OGG ."&lang=ru-RU" // ru‑RU русский язык; en-US английский язык; tr-TR турецкий язык; uk-UK украинский язык. ."&speaker=ermil" // женские: jane, oksana, alyss и omazh; мужские: zahar, ermil ."&emotion=good" // good — радостный; evil — раздраженный; neutral — нейтральный ."&key=".$GLOBALS['API'] // гуглите, как получить ключ у Яндекса, я не помню уже ."&text=".urlencode($text)); // Ограничение на длину: 2000 байт. Но я беру 1000. curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Expect:')); // не высылать заголовок на ожидание curl_exec ($ch); $result=curl_multi_getcontent($ch); curl_close ($ch); if(empty($result)) die('Error'); file_put_contents($out,$result); }
function say_text($dir,$s) { if(!is_dir($dir)) mkdir($dir);
$s=uw($s); $LIM=1000; // ограничение по количеству байт в каждом отрезке
// будем разбивать текст на строки, а затем и собирать подходящие порции для озвучки
$u=explode("\n",$s); $e=array(); for($i=0;$i<sizeof($u);$i++) { $l=$u[$i]; while(strlen($l)>$LIM) { $j=$LIM; while($j && !in_array($l[$j],array('.','?','!'))) $j--; $e[]=substr($l,0,$j+1); $l=trim(substr($l,$j+1)); } $e[]=$l; }
$k=1; $i=0; while(isset($e[$i])) { $o=''; while(isset($e[$i]) && strlen($o.$e[$i])<=$LIM) $o.=$e[$i++]."\n"; $out=$dir."/".sprintf("%03d",$k++).".txt"; if(!strlen($o)) $o.=$e[$i++]."\n"; echo "\n[$out] (".strlen($o).")---\n".wu($o); file_put_contents($out,$o); $mp3=str_replace(".txt",".mp3",$out); if(!is_file($mp3)) say(wu($o),$mp3); // озвучить очередную порцию mp3 }
// и наконец соберем все готовые куски mp3 в единый файл тупо консольным ffmpeg: $r=glob($dir."/*.mp3"); foreach($r as $n=>$l) $r[$n]=basename($l); $mymp3=basename($dir).'.mp3'; $r='cd "'.$dir.'"; ffmpeg -i "concat:'.implode('|',$r).'" -acodec copy "../'.basename($dir).'.mp3"'; exec($r); }
это перепост заметки, оригинал находится на моем сайте: https://lleo.me/dnevnik/2021/11/03
|
|