Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
R
robot-trans-platform
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
赵啸非
robot-trans-platform
Commits
9f18dc7a
Commit
9f18dc7a
authored
Jul 02, 2025
by
赵啸非
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改音频识别结果
parent
e246480e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
382 additions
and
11 deletions
+382
-11
robot-trans-manager/src/main/java/com/mortals/xhx/busiz/web/ApiSendMsgController.java
.../java/com/mortals/xhx/busiz/web/ApiSendMsgController.java
+6
-3
robot-trans-manager/src/main/java/com/mortals/xhx/common/utils/IatATWSUtil.java
...c/main/java/com/mortals/xhx/common/utils/IatATWSUtil.java
+374
-0
robot-trans-manager/src/main/java/com/mortals/xhx/common/utils/IatModelMulUtil.java
...in/java/com/mortals/xhx/common/utils/IatModelMulUtil.java
+0
-6
robot-trans-manager/src/test/java/httpclient/recording.pcm
robot-trans-manager/src/test/java/httpclient/recording.pcm
+0
-0
robot-trans-manager/src/test/java/httpclient/system.http
robot-trans-manager/src/test/java/httpclient/system.http
+2
-2
No files found.
robot-trans-manager/src/main/java/com/mortals/xhx/busiz/web/ApiSendMsgController.java
View file @
9f18dc7a
...
...
@@ -8,6 +8,7 @@ import com.mortals.framework.exception.AppException;
import
com.mortals.framework.service.ILogService
;
import
com.mortals.framework.service.impl.FileLogServiceImpl
;
import
com.mortals.xhx.base.system.upload.service.UploadService
;
import
com.mortals.xhx.common.utils.IatATWSUtil
;
import
com.mortals.xhx.common.utils.IatModelMulMain
;
import
com.mortals.xhx.common.utils.IatModelMulUtil
;
import
lombok.extern.slf4j.Slf4j
;
...
...
@@ -43,7 +44,8 @@ public class ApiSendMsgController {
@Autowired
private
UploadService
uploadService
;
private
String
hostUrl
=
"https://iat.cn-huabei-1.xf-yun.com/v1"
;
// 注意多语种识别,也支持中文音频
//private String hostUrl = "https://iat.cn-huabei-1.xf-yun.com/v1"; // 注意多语种识别,也支持中文音频
private
String
hostUrl
=
"https://iat-api.xfyun.cn/v2/iat"
;
// 注意多语种识别,也支持中文音频
private
String
appid
=
"3cc52607"
;
//在控制台-我的应用获取
private
String
apiSecret
=
"ZTdmMjFjMGYxYmJhN2VmYjFlMTg3N2Rk"
;
// 在控制台-我的应用获取
private
String
apiKey
=
"d0f73d44e996c2da9924c4476c578a30"
;
// 在控制台-我的应用获取
...
...
@@ -108,9 +110,10 @@ public class ApiSendMsgController {
byte
[]
bytes
=
file
.
getBytes
();
// IatModelMulUtil iatModelMulUtil = new IatModelMulUtil(filePath, appid);
IatModelMulUtil
iatModelMulUtil
=
new
IatModelMulUtil
(
bytes
,
appid
);
// IatModelMulUtil iatModelMulUtil = new IatModelMulUtil(bytes, appid);
IatATWSUtil
iatModelMulUtil
=
new
IatATWSUtil
(
bytes
,
appid
);
String
authUrl
=
Iat
ModelMul
Util
.
getAuthUrl
(
hostUrl
,
apiKey
,
apiSecret
);
String
authUrl
=
Iat
ATWS
Util
.
getAuthUrl
(
hostUrl
,
apiKey
,
apiSecret
);
//log.info("authUrl==>" + authUrl);
OkHttpClient
client
=
new
OkHttpClient
.
Builder
().
build
();
...
...
robot-trans-manager/src/main/java/com/mortals/xhx/common/utils/IatATWSUtil.java
0 → 100644
View file @
9f18dc7a
package
com.mortals.xhx.common.utils
;
import
com.google.gson.Gson
;
import
com.google.gson.JsonObject
;
import
lombok.extern.slf4j.Slf4j
;
import
okhttp3.HttpUrl
;
import
okhttp3.Response
;
import
okhttp3.WebSocket
;
import
okhttp3.WebSocketListener
;
import
javax.crypto.Mac
;
import
javax.crypto.spec.SecretKeySpec
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.nio.charset.Charset
;
import
java.text.SimpleDateFormat
;
import
java.util.*
;
import
java.util.concurrent.CompletableFuture
;
/**
* 语音听写
*/
@Slf4j
public
class
IatATWSUtil
extends
WebSocketListener
{
private
final
CompletableFuture
<
String
>
future
=
new
CompletableFuture
<>();
public
static
final
int
StatusFirstFrame
=
0
;
public
static
final
int
StatusContinueFrame
=
1
;
public
static
final
int
StatusLastFrame
=
2
;
public
static
final
String
encoding
=
"raw"
;
public
static
final
Gson
gson
=
new
Gson
();
// 开始时间
private
static
Date
dateBegin
=
new
Date
();
// 结束时间
private
static
Date
dateEnd
=
new
Date
();
private
static
final
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyy-MM-dd HH:mm:ss.SSS"
);
private
final
StringBuilder
responseBuilder
=
new
StringBuilder
();
public
String
file
;
// 识别音频位置*/
Decoder
decoder
=
new
Decoder
();
public
String
appid
;
private
byte
[]
bytes
;
public
IatATWSUtil
(
byte
[]
bytes
,
String
appid
)
{
// this.file = file;
this
.
bytes
=
bytes
;
this
.
appid
=
appid
;
}
@Override
public
void
onOpen
(
WebSocket
webSocket
,
Response
response
)
{
super
.
onOpen
(
webSocket
,
response
);
new
Thread
(()
->
{
//连接成功,开始发送数据
int
frameSize
=
8092
;
//每一帧音频的大小,建议每 40ms 发送 122B
int
intervel
=
40
;
int
status
=
0
;
// 音频的状态
int
totalLength
=
bytes
.
length
;
boolean
isFirst
=
true
;
int
offset
=
0
;
while
(
offset
<
totalLength
)
{
int
length
=
Math
.
min
(
frameSize
,
bytes
.
length
-
offset
);
byte
[]
buffer
=
new
byte
[
length
];
System
.
arraycopy
(
bytes
,
offset
,
buffer
,
0
,
length
);
boolean
isLast
=
(
offset
+
length
)
>=
totalLength
;
if
(
isFirst
)
{
status
=
StatusFirstFrame
;
// 仅一帧
}
else
if
(
isLast
)
{
status
=
StatusLastFrame
;
// 尾帧
}
else
{
status
=
StatusContinueFrame
;
// 中间帧
}
switch
(
status
)
{
case
StatusFirstFrame:
// 第一帧音频status = 0
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
(
"language"
,
"zh_cn"
);
//business.addProperty("language", "en_us");//英文
//business.addProperty("language", "ja_jp");//日语,在控制台可添加试用或购买
//business.addProperty("language", "ko_kr");//韩语,在控制台可添加试用或购买
//business.addProperty("language", "ru-ru");//俄语,在控制台可添加试用或购买
business
.
addProperty
(
"domain"
,
"iat"
);
business
.
addProperty
(
"accent"
,
"cn_lmz"
);
//中文方言请在控制台添加试用,添加后即展示相应参数值
//business.addProperty("nunum", 0);
//business.addProperty("ptt", 0);//标点符号
//business.addProperty("rlang", "zh-hk"); // zh-cn :简体中文(默认值)zh-hk :繁体香港(若未授权不生效,在控制台可免费开通)
//business.addProperty("vinfo", 1);
business
.
addProperty
(
"dwa"
,
"wpgs"
);
//动态修正(若未授权不生效,在控制台可免费开通)
//business.addProperty("nbest", 5);// 句子多候选(若未授权不生效,在控制台可免费开通)
//business.addProperty("wbest", 3);// 词级多候选(若未授权不生效,在控制台可免费开通)
//填充data
data
.
addProperty
(
"status"
,
StatusFirstFrame
);
data
.
addProperty
(
"format"
,
"audio/L16;rate=16000"
);
data
.
addProperty
(
"encoding"
,
"raw"
);
data
.
addProperty
(
"audio"
,
Base64
.
getEncoder
().
encodeToString
(
buffer
));
//填充frame
frame
.
add
(
"common"
,
common
);
frame
.
add
(
"business"
,
business
);
frame
.
add
(
"data"
,
data
);
log
.
info
(
"first json==>"
+
frame
);
webSocket
.
send
(
frame
.
toString
());
status
=
StatusContinueFrame
;
// 发送完第一帧改变status 为 1
break
;
case
StatusContinueFrame:
//中间帧status = 1
JsonObject
frame1
=
new
JsonObject
();
JsonObject
data1
=
new
JsonObject
();
data1
.
addProperty
(
"status"
,
StatusContinueFrame
);
data1
.
addProperty
(
"format"
,
"audio/L16;rate=16000"
);
data1
.
addProperty
(
"encoding"
,
"raw"
);
data1
.
addProperty
(
"audio"
,
Base64
.
getEncoder
().
encodeToString
(
buffer
));
frame1
.
add
(
"data"
,
data1
);
webSocket
.
send
(
frame1
.
toString
());
webSocket
.
send
(
frame1
.
toString
());
break
;
case
StatusLastFrame:
// 最后一帧音频status = 2 ,标志音频发送结束
JsonObject
frame2
=
new
JsonObject
();
JsonObject
data2
=
new
JsonObject
();
data2
.
addProperty
(
"status"
,
StatusLastFrame
);
data2
.
addProperty
(
"audio"
,
""
);
data2
.
addProperty
(
"format"
,
"audio/L16;rate=16000"
);
data2
.
addProperty
(
"encoding"
,
"raw"
);
frame2
.
add
(
"data"
,
data2
);
webSocket
.
send
(
frame2
.
toString
());
}
try
{
Thread
.
sleep
(
intervel
);
//模拟音频采样延时
}
catch
(
InterruptedException
e
)
{
}
offset
+=
length
;
isFirst
=
false
;
}
}).
start
();
}
public
CompletableFuture
<
String
>
getResultFuture
()
{
return
future
;
}
@Override
public
void
onMessage
(
WebSocket
webSocket
,
String
text
)
{
super
.
onMessage
(
webSocket
,
text
);
log
.
info
(
"onMessage==>"
+
text
);
ResponseData
resp
=
gson
.
fromJson
(
text
,
ResponseData
.
class
);
if
(
resp
!=
null
)
{
if
(
resp
.
getCode
()
!=
0
)
{
System
.
out
.
println
(
"code=>"
+
resp
.
getCode
()
+
" error=>"
+
resp
.
getMessage
()
+
" sid="
+
resp
.
getSid
());
System
.
out
.
println
(
"错误码查询链接:https://www.xfyun.cn/document/error-code"
);
return
;
}
if
(
resp
.
getData
()
!=
null
)
{
if
(
resp
.
getData
().
getResult
()
!=
null
)
{
Text
te
=
resp
.
getData
().
getResult
().
getText
();
//System.out.println(te.toString());
try
{
decoder
.
decode
(
te
);
// System.out.println("中间识别结果 ==》" + decoder.toString());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
if
(
resp
.
getData
().
getStatus
()
==
2
)
{
// todo resp.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源
System
.
out
.
println
(
"session end "
);
dateEnd
=
new
Date
();
// System.out.println(sdf.format(dateBegin) + "开始");
// System.out.println(sdf.format(dateEnd) + "结束");
//System.out.println("耗时:" + (dateEnd.getTime() - dateBegin.getTime()) + "ms");
// System.out.println("最终识别结果 ==》" + decoder.toString());
// System.out.println("本次识别sid ==》" + resp.getSid());
future
.
complete
(
decoder
.
toString
());
decoder
.
discard
();
webSocket
.
close
(
1000
,
""
);
}
else
{
// todo 根据返回的数据处理
}
}
}
}
@Override
public
void
onFailure
(
WebSocket
webSocket
,
Throwable
t
,
Response
response
)
{
super
.
onFailure
(
webSocket
,
t
,
response
);
try
{
if
(
null
!=
response
)
{
int
code
=
response
.
code
();
log
.
info
(
"onFailure code:"
+
code
);
log
.
info
(
"onFailure body:"
+
response
.
body
().
string
());
}
}
catch
(
IOException
e
)
{
// TODO Auto-generated catch block
log
.
error
(
"onFailure error:"
+
e
.
getMessage
());
}
future
.
completeExceptionally
(
t
);
}
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"
);
//System.out.println(builder);
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
);
//System.out.println(sha);
String
authorization
=
String
.
format
(
"api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\""
,
apiKey
,
"hmac-sha256"
,
"host date request-line"
,
sha
);
//System.out.println(authorization);
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
;
private
Result
result
;
public
int
getStatus
()
{
return
status
;
}
public
Result
getResult
()
{
return
result
;
}
}
public
static
class
Result
{
int
bg
;
int
ed
;
String
pgs
;
int
[]
rg
;
int
sn
;
Ws
[]
ws
;
boolean
ls
;
JsonObject
vad
;
public
Text
getText
()
{
Text
text
=
new
Text
();
StringBuilder
sb
=
new
StringBuilder
();
for
(
Ws
ws
:
this
.
ws
)
{
sb
.
append
(
ws
.
cw
[
0
].
w
);
}
text
.
sn
=
this
.
sn
;
text
.
text
=
sb
.
toString
();
text
.
sn
=
this
.
sn
;
text
.
rg
=
this
.
rg
;
text
.
pgs
=
this
.
pgs
;
text
.
bg
=
this
.
bg
;
text
.
ed
=
this
.
ed
;
text
.
ls
=
this
.
ls
;
text
.
vad
=
this
.
vad
==
null
?
null
:
this
.
vad
;
return
text
;
}
}
public
static
class
Ws
{
Cw
[]
cw
;
int
bg
;
int
ed
;
}
public
static
class
Cw
{
int
sc
;
String
w
;
}
public
static
class
Text
{
int
sn
;
int
bg
;
int
ed
;
String
text
;
String
pgs
;
int
[]
rg
;
boolean
deleted
;
boolean
ls
;
JsonObject
vad
;
@Override
public
String
toString
()
{
return
"Text{"
+
"bg="
+
bg
+
", ed="
+
ed
+
", ls="
+
ls
+
", sn="
+
sn
+
", text='"
+
text
+
'\''
+
", pgs="
+
pgs
+
", rg="
+
Arrays
.
toString
(
rg
)
+
", deleted="
+
deleted
+
", vad="
+
(
vad
==
null
?
"null"
:
vad
.
getAsJsonArray
(
"ws"
).
toString
())
+
'}'
;
}
}
//解析返回数据,仅供参考
public
static
class
Decoder
{
private
Text
[]
texts
;
private
int
defc
=
10
;
public
Decoder
()
{
this
.
texts
=
new
Text
[
this
.
defc
];
}
public
synchronized
void
decode
(
Text
text
)
{
if
(
text
.
sn
>=
this
.
defc
)
{
this
.
resize
();
}
if
(
"rpl"
.
equals
(
text
.
pgs
))
{
for
(
int
i
=
text
.
rg
[
0
];
i
<=
text
.
rg
[
1
];
i
++)
{
this
.
texts
[
i
].
deleted
=
true
;
}
}
this
.
texts
[
text
.
sn
]
=
text
;
}
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
Text
t
:
this
.
texts
)
{
if
(
t
!=
null
&&
!
t
.
deleted
)
{
sb
.
append
(
t
.
text
);
}
}
return
sb
.
toString
();
}
public
void
resize
()
{
int
oc
=
this
.
defc
;
this
.
defc
<<=
1
;
Text
[]
old
=
this
.
texts
;
this
.
texts
=
new
Text
[
this
.
defc
];
for
(
int
i
=
0
;
i
<
oc
;
i
++)
{
this
.
texts
[
i
]
=
old
[
i
];
}
}
public
void
discard
(){
for
(
int
i
=
0
;
i
<
this
.
texts
.
length
;
i
++){
this
.
texts
[
i
]=
null
;
}
}
}
}
robot-trans-manager/src/main/java/com/mortals/xhx/common/utils/IatModelMulUtil.java
View file @
9f18dc7a
...
...
@@ -30,11 +30,6 @@ import java.util.concurrent.CompletableFuture;
@Slf4j
public
class
IatModelMulUtil
extends
WebSocketListener
{
private
final
CompletableFuture
<
String
>
future
=
new
CompletableFuture
<>();
/* private static final String hostUrl = "https://iat.cn-huabei-1.xf-yun.com/v1"; // 注意多语种识别,也支持中文音频
private static final String appid = "3cc52607"; //在控制台-我的应用获取
private static final String apiSecret = "ZTdmMjFjMGYxYmJhN2VmYjFlMTg3N2Rk"; // 在控制台-我的应用获取
private static final String apiKey = "d0f73d44e996c2da9924c4476c578a30"; // 在控制台-我的应用获取
private static final String file = "E://test1.mp3"; // 识别音频位置*/
public
static
final
int
StatusFirstFrame
=
0
;
public
static
final
int
StatusContinueFrame
=
1
;
public
static
final
int
StatusLastFrame
=
2
;
...
...
@@ -74,7 +69,6 @@ public class IatModelMulUtil extends WebSocketListener {
super
.
onOpen
(
webSocket
,
response
);
new
Thread
(()
->
{
//连接成功,开始发送数据
//int frameSize = 1280; //每一帧音频的大小,建议每 40ms 发送 122B
int
frameSize
=
8092
;
//每一帧音频的大小,建议每 40ms 发送 122B
int
intervel
=
40
;
int
status
=
0
;
// 音频的状态
...
...
robot-trans-manager/src/test/java/httpclient/recording.pcm
View file @
9f18dc7a
No preview for this file type
robot-trans-manager/src/test/java/httpclient/system.http
View file @
9f18dc7a
...
...
@@ -40,9 +40,9 @@ POST {{baseUrl}}/audio/upload
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="file"; filename="
recording
.pcm"
Content-Disposition: form-data; name="file"; filename="
test
.pcm"
< ./
recording
.pcm
< ./
test
.pcm
--WebAppBoundary--
###测试链接数据库
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment