Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
H
hxwza
Project
Project
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
Graph
比较
统计图
议题
0
议题
0
列表
看板
标记
Milestones
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
注册表
注册表
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
svn
hxwza
Commits
557248f0
提交
557248f0
authored
10月 10, 2020
作者:
liupengfei
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
--no commit message
上级
50a65df8
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
201 行增加
和
2 行删除
+201
-2
EbookController.java
...om/zrqx/resource/bg/controller/ebook/EbookController.java
+201
-2
没有找到文件。
app/resource/src/main/java/com/zrqx/resource/bg/controller/ebook/EbookController.java
浏览文件 @
557248f0
package
com
.
zrqx
.
resource
.
bg
.
controller
.
ebook
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.math.BigDecimal
;
import
java.net.URL
;
import
java.nio.charset.Charset
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Base64
;
import
java.util.Comparator
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.TimeZone
;
import
java.util.stream.Collectors
;
import
javax.crypto.Mac
;
import
javax.crypto.spec.SecretKeySpec
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
...
...
@@ -23,6 +36,8 @@ import org.springframework.web.bind.annotation.RestController;
import
org.springframework.web.multipart.MultipartFile
;
import
com.github.pagehelper.PageHelper
;
import
com.google.gson.Gson
;
import
com.google.gson.JsonObject
;
import
com.zrqx.core.client.sysuser.bg.SysuserClient
;
import
com.zrqx.core.client.vo.ImportLabelVo
;
import
com.zrqx.core.commons.redis.Redis
;
...
...
@@ -81,12 +96,21 @@ import com.zrqx.resource.commons.model.qrcode.QrCode;
import
com.zrqx.resource.commons.model.resourcerelation.RelationAuthor
;
import
com.zrqx.resource.commons.solr.SolrManage
;
import
com.zrqx.resource.commons.util.WebTTSWSUtil
;
import
com.zrqx.resource.commons.util.WebTTSWSUtil.Data
;
import
com.zrqx.resource.commons.util.WebTTSWSUtil.ResponseData
;
import
com.zrqx.resource.commons.vo.bg.EpubVo
;
import
com.zrqx.resource.commons.vo.bg.ebook.EbookListVO
;
import
com.zrqx.resource.commons.vo.bg.ebook.EbookVO
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
okhttp3.HttpUrl
;
import
okhttp3.OkHttpClient
;
import
okhttp3.Request
;
import
okhttp3.Response
;
import
okhttp3.WebSocket
;
import
okhttp3.WebSocketListener
;
import
okio.ByteString
;
import
tk.mybatis.mapper.entity.Example
;
...
...
@@ -151,6 +175,11 @@ public class EbookController {
private
QrCodeService
qrCodeService
;
@Value
(
"${qrcode-upload-path}"
)
private
String
qrCodeUploadPath
;
private
static
final
String
hostUrl
=
"https://tts-api.xfyun.cn/v2/tts"
;
//http url 不支持解析 ws/wss schema
private
static
final
String
appid
=
"5f800e7f"
;
//到控制台-语音合成页面获取
private
static
final
String
apiSecret
=
"fcf21aa34ac9b1c89a5ae080e86f406c"
;
//到控制台-语音合成页面获取
private
static
final
String
apiKey
=
"793094b3d3f8dd4c4f57193499d6cc5a"
;
//到控制台-语音合成页面获取
public
static
final
Gson
json
=
new
Gson
();
@ApiOperation
(
"保存电子书"
)
@PostMapping
(
"/save"
)
...
...
@@ -588,7 +617,7 @@ public class EbookController {
for
(
int
i
=
0
;
i
<
textList
.
size
()
;
i
++)
{
try
{
String
fileName
=
i
+
1
+
""
;
String
articlePath
=
WebTTSWSUtil
.
testToAudio
(
textList
.
get
(
i
),
article
.
getId
(),
fileName
);
String
articlePath
=
testToAudio
(
textList
.
get
(
i
),
article
.
getId
(),
fileName
);
ArticleToAudio
articleToAudio
=
new
ArticleToAudio
();
articleToAudio
.
setArticleId
(
article
.
getId
());
articleToAudio
.
setUploadTime
(
new
Date
());
...
...
@@ -719,7 +748,7 @@ public class EbookController {
for
(
int
i
=
0
;
i
<
textList
.
size
()
;
i
++)
{
try
{
String
fileName
=
i
+
1
+
""
;
String
articlePath
=
WebTTSWSUtil
.
testToAudio
(
textList
.
get
(
i
),
article
.
getId
(),
fileName
);
String
articlePath
=
testToAudio
(
textList
.
get
(
i
),
article
.
getId
(),
fileName
);
ArticleToAudio
articleToAudio
=
new
ArticleToAudio
();
articleToAudio
.
setArticleId
(
article
.
getId
());
articleToAudio
.
setUploadTime
(
new
Date
());
...
...
@@ -795,6 +824,176 @@ public class EbookController {
* @param length 指定长度
* @return
*/
public
static
String
testToAudio
(
String
text
,
String
filePath
,
String
fileName
)
throws
Exception
{
// 构建鉴权url
String
authUrl
=
getAuthUrl
(
hostUrl
,
apiKey
,
apiSecret
);
OkHttpClient
client
=
new
OkHttpClient
.
Builder
().
build
();
//将url中的 schema http://和https://分别替换为ws:// 和 wss://
String
url
=
authUrl
.
toString
().
replace
(
"http://"
,
"ws://"
).
replace
(
"https://"
,
"wss://"
);
Request
request
=
new
Request
.
Builder
().
url
(
url
).
build
();
// 存放音频的文件
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyyMMddHHmmssSSS"
);
File
file
=
new
File
(
"/opt/upload/hxwza/audio/"
+
filePath
);
if
(!
file
.
exists
())
{
file
.
mkdirs
();
}
File
f
=
new
File
(
"/opt/upload/hxwza/audio/"
+
filePath
+
"/"
+
fileName
+
".mp3"
);
String
path
=
"/audio/"
+
filePath
+
"/"
+
fileName
+
".mp3"
;
if
(!
f
.
exists
())
{
f
.
createNewFile
();
}
FileOutputStream
os
=
new
FileOutputStream
(
f
);
WebSocket
webSocket
=
client
.
newWebSocket
(
request
,
new
WebSocketListener
()
{
@Override
public
void
onOpen
(
WebSocket
webSocket
,
Response
response
)
{
super
.
onOpen
(
webSocket
,
response
);
try
{
System
.
out
.
println
(
response
.
body
().
string
());
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
//发送数据
JsonObject
frame
=
new
JsonObject
();
JsonObject
business
=
new
JsonObject
();
JsonObject
common
=
new
JsonObject
();
JsonObject
data
=
new
JsonObject
();
// 填充common
common
.
addProperty
(
"app_id"
,
appid
);
//填充business
business
.
addProperty
(
"aue"
,
"lame"
);
business
.
addProperty
(
"sfl"
,
1
);
business
.
addProperty
(
"tte"
,
"UTF8"
);
//小语种必须使用UNICODE编码
business
.
addProperty
(
"vcn"
,
"xiaoyan"
);
//到控制台-我的应用-语音合成-添加试用或购买发音人,添加后即显示该发音人参数值,若试用未添加的发音人会报错11200
business
.
addProperty
(
"pitch"
,
50
);
business
.
addProperty
(
"speed"
,
50
);
//填充data
data
.
addProperty
(
"status"
,
2
);
//固定位2
try
{
data
.
addProperty
(
"text"
,
Base64
.
getEncoder
().
encodeToString
(
text
.
getBytes
(
"utf8"
)));
//使用小语种须使用下面的代码,此处的unicode指的是 utf16小端的编码方式,即"UTF-16LE"”
//data.addProperty("text", Base64.getEncoder().encodeToString(text.getBytes("UTF-16LE")));
}
catch
(
UnsupportedEncodingException
e
)
{
e
.
printStackTrace
();
}
//填充frame
frame
.
add
(
"common"
,
common
);
frame
.
add
(
"business"
,
business
);
frame
.
add
(
"data"
,
data
);
webSocket
.
send
(
frame
.
toString
());
}
@Override
public
void
onMessage
(
WebSocket
webSocket
,
String
text
)
{
super
.
onMessage
(
webSocket
,
text
);
//处理返回数据
System
.
out
.
println
(
"receive=>"
+
text
);
ResponseData
resp
=
null
;
try
{
resp
=
json
.
fromJson
(
text
,
ResponseData
.
class
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
if
(
resp
!=
null
)
{
if
(
resp
.
getCode
()
!=
0
)
{
System
.
out
.
println
(
"error=>"
+
resp
.
getMessage
()
+
" sid="
+
resp
.
getSid
());
return
;
}
if
(
resp
.
getData
()
!=
null
)
{
String
result
=
resp
.
getData
().
audio
;
byte
[]
audio
=
Base64
.
getDecoder
().
decode
(
result
);
try
{
os
.
write
(
audio
);
os
.
flush
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
if
(
resp
.
getData
().
status
==
2
)
{
// todo resp.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源
System
.
out
.
println
(
"session end "
);
System
.
out
.
println
(
"合成的音频文件保存在:"
+
f
.
getPath
());
webSocket
.
close
(
1000
,
""
);
try
{
os
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
}
}
@Override
public
void
onMessage
(
WebSocket
webSocket
,
ByteString
bytes
)
{
super
.
onMessage
(
webSocket
,
bytes
);
}
@Override
public
void
onClosing
(
WebSocket
webSocket
,
int
code
,
String
reason
)
{
super
.
onClosing
(
webSocket
,
code
,
reason
);
System
.
out
.
println
(
"socket closing"
);
}
@Override
public
void
onClosed
(
WebSocket
webSocket
,
int
code
,
String
reason
)
{
super
.
onClosed
(
webSocket
,
code
,
reason
);
System
.
out
.
println
(
"socket closed"
);
}
@Override
public
void
onFailure
(
WebSocket
webSocket
,
Throwable
t
,
Response
response
)
{
super
.
onFailure
(
webSocket
,
t
,
response
);
System
.
out
.
println
(
"connection failed"
);
}
});
return
path
;
}
public
static
String
getAuthUrl
(
String
hostUrl
,
String
apiKey
,
String
apiSecret
)
throws
Exception
{
URL
url
=
new
URL
(
hostUrl
);
SimpleDateFormat
format
=
new
SimpleDateFormat
(
"EEE, dd MMM yyyy HH:mm:ss z"
,
Locale
.
US
);
format
.
setTimeZone
(
TimeZone
.
getTimeZone
(
"GMT"
));
String
date
=
format
.
format
(
new
Date
());
StringBuilder
builder
=
new
StringBuilder
(
"host: "
).
append
(
url
.
getHost
()).
append
(
"\n"
).
//
append
(
"date: "
).
append
(
date
).
append
(
"\n"
).
//
append
(
"GET "
).
append
(
url
.
getPath
()).
append
(
" HTTP/1.1"
);
Charset
charset
=
Charset
.
forName
(
"UTF-8"
);
Mac
mac
=
Mac
.
getInstance
(
"hmacsha256"
);
SecretKeySpec
spec
=
new
SecretKeySpec
(
apiSecret
.
getBytes
(
charset
),
"hmacsha256"
);
mac
.
init
(
spec
);
byte
[]
hexDigits
=
mac
.
doFinal
(
builder
.
toString
().
getBytes
(
charset
));
String
sha
=
Base64
.
getEncoder
().
encodeToString
(
hexDigits
);
String
authorization
=
String
.
format
(
"hmac username=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\""
,
apiKey
,
"hmac-sha256"
,
"host date request-line"
,
sha
);
HttpUrl
httpUrl
=
HttpUrl
.
parse
(
"https://"
+
url
.
getHost
()
+
url
.
getPath
()).
newBuilder
().
//
addQueryParameter
(
"authorization"
,
Base64
.
getEncoder
().
encodeToString
(
authorization
.
getBytes
(
charset
))).
//
addQueryParameter
(
"date"
,
date
).
//
addQueryParameter
(
"host"
,
url
.
getHost
()).
//
build
();
return
httpUrl
.
toString
();
}
public
static
class
ResponseData
{
private
int
code
;
private
String
message
;
private
String
sid
;
private
Data
data
;
public
int
getCode
()
{
return
code
;
}
public
String
getMessage
()
{
return
this
.
message
;
}
public
String
getSid
()
{
return
sid
;
}
public
Data
getData
()
{
return
data
;
}
}
public
static
class
Data
{
private
int
status
;
//标志音频是否返回结束 status=1,表示后续还有音频返回,status=2表示所有的音频已经返回
private
String
audio
;
//返回的音频,base64 编码
private
String
ced
;
// 合成进度
}
/**
* 把原始字符串分割成指定长度的字符串列表
* @param inputString 原始字符串
* @param length 指定长度
* @return
*/
public
static
List
<
String
>
getStrList
(
String
inputString
,
int
length
)
{
int
size
=
inputString
.
length
()
/
length
;
if
(
inputString
.
length
()
%
length
!=
0
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论