手把手给文章添加TTS朗读功能

如题,这个想法在博客界也只有本人会去折腾,之前实现过给wordpress文章加上TTS语音朗读,后来看到麦田一根葱也跟着加上这个功能(他的不知道用什么方法,不过语音很死板),但本站使用的方法由于稳定性问题把它给撤下了。

PS:最新更新:给博客添加TTS语音朗读 简单快速版

今天,因为特殊原因需要登录百度云后台,发现更新了这方面的服务,并且主页显示了各种已经开启的开发选项,其中百度语音合成就再次吸引住我的目光,OK,既然这样,我们就再折腾一次吧!相信百度经过这么久的时间应该会稳定了吧。

查看演示请换一篇文章,文章开头有播放按钮,这篇文章字数太多,自动跳过。

也因为之前实现的方法是没有用apiKey来折腾,估计稳定性有限制,于是决定再次折腾!

之前实现的方法是这样的:

http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=5&text=你好这是百度语音合成

播放器播放上面地址即可听到语音朗读!后面文字部分直接获取整篇文章,所以可以使用播放器播放这个URL链接,这方法虽然简单,但是今天测试,发现声音和原来不一样了,变成了低沉的老人音。

再试试APIKey那个,可以有很多声音选择,OK,开始折腾。

问题来了:

1.百度语音不支持超过900字(所以这篇文章不支持就跳过了),原以为是因为无APIKey造成的,今天折腾完以后,还是不行。

2.那么我就把文章进行分割分组,让播放器进行批量按顺序播放。

3.目前只能分3组,因为大部分文章不超过2700字。

OK,以上就这样解决,上次没有记方法,后来又得重新折腾,所以这次决定分享一下方法,之前也有人问,下面直接说步骤:

1.首先进入百度云申请APIKEY,如果不想申请,直接用文章开头那个方法,只是声音不好听。

2.拷贝如下代码:

<?php

function mbStrSplit ($string, $len=1) {
$start = 0;
$strlen = mb_strlen($string);
while ($strlen) {
$array[] = mb_substr($string,$start,$len,"utf8");
$string = mb_substr($string, $len, $strlen,"utf8");
$strlen = mb_strlen($string);
}
return $array;
}

function match_chinese($chars,$encoding='utf8') //过滤特殊字符串
{
$pattern =($encoding=='utf8')?'/[\x{4e00}-\x{9fa5}a-zA-Z0-9,,。 ]/u':'/[\x80-\xFF]/';
preg_match_all($pattern,$chars,$result);
$temp =join('',$result[0]);
return $temp;
}

$zishu=mb_strlen(preg_replace('/\s/','',html_entity_decode(strip_tags($post->post_content))),'UTF-8');
if($zishu<=2700){  //字数限制2700,超过不输出朗读功能。

$str = "你好吗"; //删除$str =后面的内容,替换成这个:strip_tags($post->post_content);
$str = str_replace("、",",",$str );//保留顿号
$str=match_chinese($str);
$r = mbStrSplit($str, 900);
$qian="http://tsn.baidu.com/text2audio?tex=";
$hou=""; //例子:&per=0&spd=5&pit=5&vol=5&aue=3&cuid=123456PHP&tok=25.d7787ede620fd2fd516f119ab668f50b.2582090.1546809998.282335-15079228&lan=zh&ctp=1复制这一段你的tok号在双引号里面

//以上是文章切割部分

//下面是百度云部分
define('DEMO_CURL_VERBOSE', false);
# 填写网页上申请的appkey 如 $apiKey="g8eBUMSokVB1BHGmgxxxxxx"
$apiKey = "";
# 填写网页上申请的APP SECRET 如 $secretKey="94dc99566550d87f8fa8ece112xxxxx"
$secretKey = "";
# text 的内容为"欢迎使用百度语音合成"的urlencode,utf-8 编码
# 可以百度搜索"urlencode"
//$text = strip_tags($post->post_content);
//$text2 = iconv("UTF-8", "GBK", $text);
//echo "text length :" . mb_strlen($text2, "GBK") . "\n";
#发音人选择, 0为普通女声,1为普通男生,3为情感合成-度逍遥,4为情感合成-度丫丫,默认为普通女声
$per = 0;
#语速,取值0-15,默认为5中语速
$spd = 5;
#音调,取值0-15,默认为5中语调
$pit = 5;
#音量,取值0-9,默认为5中音量
$vol = 5;
// 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
$aue = 3;
$formats = array(3 => 'mp3', 4 => 'pcm', 5 => 'pcm', 6 => 'wav');
$format = $formats[$aue];
$cuid = "123456PHP";
/** 公共模块获取token开始 */
$auth_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=".$apiKey."&client_secret=".$secretKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $auth_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//信任任何证书
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
// 检查证书中是否设置域名,0不验证
curl_setopt($ch, CURLOPT_VERBOSE, DEMO_CURL_VERBOSE);
$res = curl_exec($ch);
if (curl_errno($ch)) {
print curl_error($ch);
}
curl_close($ch);
//echo "Token URL response is " . $res . "\n";
$response = json_decode($res, true);
if (!isset($response['access_token'])) {
echo "ERROR TO OBTAIN TOKEN\n";
exit(1);
}
if (!isset($response['scope'])) {
echo "ERROR TO OBTAIN scopes\n";
exit(2);
}
if (!in_array('audio_tts_post',explode(" ", $response['scope']))) {
echo "DO NOT have tts permission\n";
// 请至网页上应用内开通语音合成权限
exit(3);
}
$token = $response['access_token'];
//echo "token = $token ; expireInSeconds: ${response['expires_in']}\n\n";
/** 公共模块获取token结束 */
/** 拼接参数开始 **/
// tex=$text&lan=zh&ctp=1&cuid=$cuid&tok=$token&per=$per&spd=$spd&pit=$pit&vol=$vol
$params = array(
'tex' => urlencode($text), // 为避免+等特殊字符没有编码,此处需要2次urlencode。
'per' => $per,
'spd' => $spd,
'pit' => $pit,
'vol' => $vol,
'aue' => $aue,
'cuid' => $cuid,
'tok' => $token,
'lan' => 'zh', //固定参数
'ctp' => 1, // 固定参数
);
$paramsStr = http_build_query($params);
$url = 'http://tsn.baidu.com/text2audio';
$urltest = $url . '?' . $paramsStr;
echo $urltest; //删除这行代码!
/** 拼接参数结束 **/
$g_has_error = true;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $paramsStr);
function read_header($ch, $header) {
global $g_has_error;

$comps = explode(":", $header);
// 正常返回的头部 Content-Type: audio/*
// 有错误的如 Content-Type: application/json
if (count($comps) >= 2) {
if (strcasecmp(trim($comps[0]), "Content-Type") == 0) {
if (strpos($comps[1], "audio/") > 0) {
$g_has_error = false;
} else {
echo $header ." , has error \n";
}
}
}
return strlen($header);
}
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
$data = curl_exec($ch);
if (curl_errno($ch)) {
echo curl_error($ch);
exit(2);
}
curl_close($ch);
$file = $g_has_error ? "result.txt" : "result." . $format;
file_put_contents($file, $data);
//echo "\n$file saved successed, please open it \n";

?>

<?php if ($zishu<=2700): ?> //字数限制2700,超过不输出朗读功能。

<span class="du">
<video id="langdu" style="display:none">
<source id="source" src="<?php echo $qian.$r[0].$hou; ?>" type="video/mp4">
</video>

<script type="text/javascript">
function playPause() {
var music = document.getElementById('langdu');
var music_btn = document.getElementById('music_btn01');

if (music.paused) {
music.play();
music_btn.src = '<?php bloginfo('template_url'); ?>/images/zanting.png'; //播放图片
var aud = document.getElementById("langdu");
aud.onended = function() {
aud.src = "<?php echo $qian.$r[1].$hou; ?>"
aud.play();
aud.addEventListener("ended", function() {
aud.src = "<?php echo $qian.$r[2].$hou; ?>"
aud.play();
aud.addEventListener("ended", function() {
aud.pause();
}, false);
}, false);
};

} else {
music.pause();
music_btn.src = '<?php bloginfo('template_url'); ?>/images/bofang.png'; //暂停图片
}
}

</script>

<a href="javascript:playPause();"><img src="<?php bloginfo('template_url'); ?>/images/bofang.png" width="25" height="25" id="music_btn01" border="0"></a>
</span>

<?php endif;?>

3.复制以上代码粘贴到single.php文章页面文件的<?php the_content(); ?>前面,代码中的png播放暂停按钮图片自己从本站右键下载放到你主题的images目录下,如果路径不同,自己修改图片路径。

4.保存,看看你的文章页。

5.先执行第2步红色字部分。

6.再执行第2步蓝色字部分。

5.大功告成!

好吧,不要觉得很繁琐,其实很简单,只是解释比较多,当然,你要是有更简单的方法,请告知。

PS:播放按钮用CSS的话,js代码也简化了,播放按钮CSS和js代码:

页面调用按钮代码:

<div class='music_btn01'></div>

CSS按钮:

.music_btn01 {
box-sizing: border-box;
width: 0;
height: 20px;
margin-left: 2px;
border-color: transparent transparent transparent #b7b7b7;
transition: 100ms all ease;
cursor: pointer;
margin-top: 4px;
border-style: solid;
border-width: 10px 0 8px 15px;
}
.paused {
border-style: double;
border-width: 0px 0 0px 15px;
}

.music_btn01:hover {
border-color: transparent transparent transparent #404040;
}

JS代码:

<script>
$(document).ready(function() {
var music = document.getElementById('langdu');
var btn = $(".music_btn01");
btn.click(function() {
if (music.paused) {
music.play();
btn.toggleClass("paused");
} else {
music.pause();
btn.toggleClass("paused");
}
});
});
</script>

 

 

分类:网络博客 标签:,,,

上一篇:纯CSS绘制灯泡

下一篇:代码高亮,这配色能亮瞎你的眼睛

已经有19条评论!

Loading...
  1. 百度手机端APP里就就集成了这个语音朗读!感觉还是很不错的! [坏笑]

    沙发!
  2. 这个挺有意思,有空也研究下~~ [坏笑]

    板凳!
  3. 虽然没啥大用(玩博客的文盲应该lim->0吧?),不过赞还是要点的

    地板!
    • @老虎 其实不是给文盲用的,是解放眼睛,哈哈。。记得当时安卓可以朗读小说文本的时候,多少人大赞TTS功能,这功能甚至今天用在各种人机交流上,比如车站的语音广播,小爱同学等等。

  4. [耍酷] 对这个没需求,貌似你这个语音说话也听着瘆人…… [坏笑]

    4F
  5. 没看到朗读的按钮??

    5F
  6. 这个功能还是挺有趣的,我觉得比较适合非技术类文章,这女读代码真的听不懂 [困惑]

    6F
  7. 感觉折腾一下还可以,语音朗读这个功能大概很多时候用不到

    7F
    • @ZAERA 我说我自己会用你可能不相信,哈哈。。我自己有收藏文章,有时候会听一下,另外,我发现很多人没办法看完整篇文章,有的只是看看标题就评论,有这个现象吧?然后如果没时间看,那就按下播放,至少会听完的,如果别人博客有,我会选择这样方式,因为手头忙,听没问题,一切为了节省时间,哈哈。

  8. 感觉还挺有意思的,回头研究下~~对了,为啥是video而不是audio标签呢?

    8F
  9. 插放弹出一个黑色的播放器窗口,失败。我看了另一个模版实现是没有弹窗的。通过播放器按钮来实现。

    9F

怎么样?你也说一句吧!

gravatar

冷笑 忧伤 恶魔 笑脸 红脸 咧嘴笑 吃惊 惊讶 困惑 耍酷
大笑 抓狂 痛苦 转眼珠 眨眼 好主意 囧 无表情 哭泣 坏笑