前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用Node中间层,对接讯飞实现h5页面文章tts(自动朗读)功能

利用Node中间层,对接讯飞实现h5页面文章tts(自动朗读)功能

作者头像
super.x
发布2019-04-12 15:17:52
1.2K0
发布2019-04-12 15:17:52
举报

很多时候在看文章的时候都会有自动朗读文章内容的功能,那么这种功能如何在h5上是怎么实现的呢,下面就拿我司一个基本需求作为线索,看是怎么一步一步实现的

需求提出

经过我司产品经理的想法,做出如下功能 1.自动朗读当前h5页面文章

竞品——》

竞品功能.png
竞品功能.png

调研发现,竞品h5是app原生实现,而我司都是h5实现文章阅读,所以开始进行h5的调研

对接科大讯飞在线语音合成

调研发现科大讯飞的在线语音合成可以基本提供相应功能,决定做一个demo来测试效果

1.控制台开通权限

clipboard.png
clipboard.png

2.阅读文档

clipboard.png
clipboard.png

具体代码如下

代码语言:javascript
复制
import axios from 'axios'
import * as md5 from './md5'

axios.defaults.withCredentials = true

let Appid = 'xxxxx'
let apiKey = 'xxxxxx'
let CurTime = Date.parse(new Date()) / 1000
let param = {
    auf: 'audio/L16;rate=16000',
    aue: 'lame',
    voice_name: 'xiaoyan',
    speed: '50',
    volume: '50',
    pitch: '50',
    engine_type: 'intp65',
    text_type: 'text'
}
let Base64 = {
    encode: (str) => {
        return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
            function toSolidBytes(match, p1) {
                return String.fromCharCode('0x' + p1);
            }));
    },
    decode: (str) => {
        // Going backwards: from bytestream, to percent-encoding, to original string.
        return decodeURIComponent(atob(str).split('').map(function (c) {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
    }
}
let xp = Base64.encode(JSON.stringify(param))
let CheckSum = md5.hex_md5(apiKey + CurTime + xp)

let headers = {
  'X-Appid': Appid,
  'X-CurTime': CurTime,
  'X-Param': xp,
  'X-CheckSum': CheckSum,
  'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
}

export function getAloud (text) {
    // let data = {
    //   text: encodeURI(text)
    // }
    var formdata = new FormData()
    formdata.append('text', text)
    return axios({
        baseURL: window.location.href.includes('demo') ? 'https://api.xfyun.cn' : '/tts',
        method: 'POST',
        url: '/v1/service/v1/tts',
        headers: {
          ...headers
        },
        data: formdata
    })
}

经过测试,是返回二进制文件流了但是前端试了各种办法没有实现流的播放

node中间层

引入node中间层是考虑到文件可以存储,可以放到cdn上进行缓存,可以减少相似文章的请求科大讯飞接口,可以减少流量的产生,所以决定加入node中间层

ps:考拉阅读有node服务器作为一些中间层的处理。主要技术栈是node + koa2 + pm2

代码语言:javascript
复制
const md5 = require('../lib/md5.js')
const fs = require('fs')
const path = require('path')
const marked = require('marked')
const request = require('request')


let Appid = ''
let apiKey = ''
let CurTime
let param = {
    auf: 'audio/L16;rate=16000',
    aue: 'lame',
    voice_name: 'x_yiping',
    speed: '40',
    volume: '50',
    pitch: '50',
    engine_type: 'intp65',
    text_type: 'text'
}

var b = new Buffer(JSON.stringify(param));
let xp = b.toString('base64')
let CheckSum

let headers

exports.getAloud = async ctx => {
    CurTime = Date.parse(new Date()) / 1000
    CheckSum = md5.hex_md5(apiKey + CurTime + xp)
    headers = {
        'X-Appid': Appid,
        'X-CurTime': CurTime,
        'X-Param': xp,
        'X-CheckSum': CheckSum,
        'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
    }
    let id = ctx.request.body.id
    let text = ctx.request.body.text
    console.log(ctx.query)
    var postData = {
        text: text
    }
    let r = request({
        url: 'http://api.xfyun.cn/v1/service/v1/tts',   // 请求的URL
        method: 'POST',                   // 请求方法
        headers: headers,
        formData: postData
    }, function (error, response, body) {
        // console.log('error:', error); // Print the error if one occurred
        // console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
        // console.log('body:', body); // Print the HTML for the Google homepage.
    })
    await new Promise((resolve, reject) => {
        let filePath = path.join(__dirname, 'public/') + `/${id}.mp3`
        const upStream = fs.createWriteStream(filePath)
        r.pipe(upStream)
        upStream.on('close', () => {
            console.log('download finished');
            resolve()
        });
    })
    .then((res) => {
        ctx.body = {
            code: 200,
            message: '语音合成成功',
            data: {
                url: 'https://fe.koalareading.com/file/' + id + '.mp3'
            }
        }
    })
}

主要运用request的管道流概念 把后台返回的二进制文件导入到流里面,在写入到文件里面 最后返回一个url给前端播放使用

此致,测试

clipboard.png
clipboard.png
代码语言:javascript
复制
//返回url。相同文章唯一id区分,可以缓存使用
https://fe.koalareading.com/file/1112.mp3

需求demo完成

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
语音合成
语音合成(Text To Speech,TTS)满足将文本转化成拟人化语音的需求,打通人机交互闭环。提供多场景、多语言的音色选择,支持 SSML 标记语言,支持自定义音量、语速等参数,让发音更专业、更符合场景需求。语音合成广泛适用于智能客服、有声阅读、新闻播报、人机交互等业务场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档