Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
CivWeb
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ReactWeb5
CivWeb
Commits
dbf1cdfc
Commit
dbf1cdfc
authored
Mar 28, 2024
by
xuchaozou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 完成语音播报
parent
e0a0815e
Pipeline
#86576
waiting for manual action with stages
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
145 additions
and
22 deletions
+145
-22
index.jsx
src/components/SoundAi/Ui/Dialog/index.jsx
+52
-14
index.js
...nents/SoundAi/core/core/SpeechSynthesisUtterance/index.js
+56
-0
PandaRecordWebSocket.js
...ponents/SoundAi/core/core/sockets/PandaRecordWebSocket.js
+14
-0
PandaWebSocket.js
src/components/SoundAi/core/core/sockets/PandaWebSocket.js
+1
-1
index.js
...onents/SoundAi/core/directive/CloseMenuDirective/index.js
+5
-3
index.js
...ponents/SoundAi/core/directive/OpenMenuDirective/index.js
+1
-1
TestDirective.js
src/components/SoundAi/core/directive/TestDirective.js
+7
-1
index.js
src/components/SoundAi/core/index.js
+3
-1
testCommand.js
src/components/SoundAi/testCommand.js
+6
-1
No files found.
src/components/SoundAi/Ui/Dialog/index.jsx
View file @
dbf1cdfc
...
@@ -4,7 +4,7 @@ import { Tooltip, Typography } from 'antd'
...
@@ -4,7 +4,7 @@ import { Tooltip, Typography } from 'antd'
import
{
Fragment
,
useCallback
,
useContext
,
useEffect
,
useRef
,
useState
}
from
'react'
import
{
Fragment
,
useCallback
,
useContext
,
useEffect
,
useRef
,
useState
}
from
'react'
import
{
event
}
from
'@wisdom-utils/utils'
import
{
event
}
from
'@wisdom-utils/utils'
import
moment
from
'moment'
import
moment
from
'moment'
import
{
Directive
,
AllDirectiveTypes
,
CloseSessionDirective
}
from
'../../core'
import
{
Directive
,
AllDirectiveTypes
,
CloseSessionDirective
,
PandaSpeechSynthesisUtterance
}
from
'../../core'
import
context
from
'../../config'
import
context
from
'../../config'
import
SparkDirective
from
'../../core/directive/SparkDirective'
import
SparkDirective
from
'../../core/directive/SparkDirective'
...
@@ -19,8 +19,10 @@ const Dialog = props => {
...
@@ -19,8 +19,10 @@ const Dialog = props => {
const
timeRef
=
useRef
(
null
)
const
timeRef
=
useRef
(
null
)
const
isDebug
=
globalConfig
.
get
(
"isDebug"
)
const
isDebug
=
globalConfig
.
get
(
"isDebug"
)
const
currentDirectiveRef
=
useRef
(
null
)
const
currentDirectiveRef
=
useRef
(
null
)
const
pandaSpeechSynthesisUtteranceRef
=
useRef
(
null
)
//是否开启系统语音
//是否开启系统语音
const
isOpenSystemSound
=
globalConfig
.
getIn
([
'key'
,
'isOpenSystemSound'
])
const
isOpenSystemSound
=
globalConfig
.
getIn
([
'key'
,
'isOpenSystemSound'
])
const
defaultEmptyMsg
=
"亲,我暂时还未理解你的意思,请换一种方式表达或者描述更加具体"
const
[
data
,
setData
]
=
useState
(()
=>
[{
const
[
data
,
setData
]
=
useState
(()
=>
[{
role
:
"system"
,
role
:
"system"
,
...
@@ -47,6 +49,7 @@ const Dialog = props => {
...
@@ -47,6 +49,7 @@ const Dialog = props => {
closeDirectiveRef
.
current
=
new
Directive
({
closeDirectiveRef
.
current
=
new
Directive
({
directiveTypes
:
[
CloseSessionDirective
]
directiveTypes
:
[
CloseSessionDirective
]
})
})
pandaSpeechSynthesisUtteranceRef
.
current
=
new
PandaSpeechSynthesisUtterance
()
if
(
globalConfig
.
get
(
'key'
).
isOpenSparkModel
)
{
if
(
globalConfig
.
get
(
'key'
).
isOpenSparkModel
)
{
directiveRef
.
current
.
directiveTypes
.
push
(
SparkDirective
)
directiveRef
.
current
.
directiveTypes
.
push
(
SparkDirective
)
directiveRef
.
current
.
_directiveTypes
.
push
(
SparkDirective
)
directiveRef
.
current
.
_directiveTypes
.
push
(
SparkDirective
)
...
@@ -56,14 +59,24 @@ const Dialog = props => {
...
@@ -56,14 +59,24 @@ const Dialog = props => {
return
()
=>
{
return
()
=>
{
event
.
off
(
"aiSound:finish"
,
finish
)
event
.
off
(
"aiSound:finish"
,
finish
)
event
.
off
(
"aiSound:frame"
,
frame
)
event
.
off
(
"aiSound:frame"
,
frame
)
if
(
pandaSpeechSynthesisUtteranceRef
.
current
)
{
pandaSpeechSynthesisUtteranceRef
.
current
.
clear
()
pandaSpeechSynthesisUtteranceRef
.
current
=
null
}
destroyTime
()
destroyTime
()
}
}
},
[])
},
[])
const
finish
=
useCallback
(
async
({
resultText
})
=>
{
const
finish
=
useCallback
(
async
({
resultText
})
=>
{
if
(
!
resultText
)
return
if
(
!
resultText
)
return
if
(
isOpenSystemSound
)
{
pandaSpeechSynthesisUtteranceRef
.
current
?.
clear
()
pandaRecordWebSocketRef
.
current
&&
pandaRecordWebSocketRef
.
current
.
setStatus
(
"pause"
)
if
(
pandaRecordWebSocketRef
.
current
)
{
if
(
isOpenSystemSound
)
{
pandaRecordWebSocketRef
.
current
.
stopRecorderManager
()
}
// else {
// pandaRecordWebSocketRef.current.setStatus("pause")
// }
}
}
const
directive
=
directiveRef
.
current
.
parse
({
const
directive
=
directiveRef
.
current
.
parse
({
text
:
resultText
text
:
resultText
...
@@ -77,24 +90,45 @@ const Dialog = props => {
...
@@ -77,24 +90,45 @@ const Dialog = props => {
let
resultMsg
=
""
let
resultMsg
=
""
await
directive
.
excute
({
await
directive
.
excute
({
sendMsg
:
msg
=>
{
sendMsg
:
msg
=>
{
isOpenSystemSound
&&
pandaSpeechSynthesisUtteranceRef
.
current
.
push
(
msg
)
resultMsg
+=
msg
resultMsg
+=
msg
updateLastData
({
updateLastData
({
content
:
resultMsg
content
:
resultMsg
})
})
}
}
})
})
if
(
isOpenSystemSound
)
{
if
(
isOpenSystemSound
)
{
pandaRecordWebSocketRef
.
current
&&
pandaRecordWebSocketRef
.
current
.
setStatus
(
"playing"
)
destroyTime
()
await
pandaSpeechSynthesisUtteranceRef
.
current
.
speakEnd
()
startTime
()
}
}
if
(
pandaRecordWebSocketRef
.
current
)
{
if
(
isOpenSystemSound
)
{
pandaRecordWebSocketRef
.
current
.
resumeRecorderManager
()
}
// else {
// pandaRecordWebSocketRef.current.setStatus("playing")
// }
}
currentDirectiveRef
.
current
=
null
currentDirectiveRef
.
current
=
null
return
return
}
}
sendContent
({
sendContent
({
role
:
"system"
,
role
:
"system"
,
content
:
"亲,我暂时还未理解你的意思,请换一种方式表达或者描述更加具体"
content
:
defaultEmptyMsg
})
})
if
(
isOpenSystemSound
)
{
if
(
isOpenSystemSound
)
{
pandaRecordWebSocketRef
.
current
&&
pandaRecordWebSocketRef
.
current
.
setStatus
(
"playing"
)
pandaSpeechSynthesisUtteranceRef
.
current
.
push
(
defaultEmptyMsg
)
await
pandaSpeechSynthesisUtteranceRef
.
current
.
speakEnd
()
}
if
(
pandaRecordWebSocketRef
.
current
)
{
if
(
isOpenSystemSound
)
{
pandaRecordWebSocketRef
.
current
.
resumeRecorderManager
()
}
// else {
// pandaRecordWebSocketRef.current.setStatus("playing")
// }
}
}
},
[])
},
[])
...
@@ -116,14 +150,10 @@ const Dialog = props => {
...
@@ -116,14 +150,10 @@ const Dialog = props => {
const
closeSession
=
({
resultText
})
=>
{
const
closeSession
=
({
resultText
})
=>
{
if
(
currentDirectiveRef
.
current
)
{
if
(
currentDirectiveRef
.
current
)
{
currentDirectiveRef
.
current
.
closeResponse
()
currentDirectiveRef
.
current
.
closeResponse
()
pandaRecordWebSocketRef
.
current
.
wsClose
()
delayStartSocket
()
pandaRecordWebSocketRef
.
current
.
setStatus
(
"pause"
)
setTimeout
(()
=>
{
pandaRecordWebSocketRef
.
current
.
setStatus
(
"playing"
)
},
500
)
}
else
{
}
else
{
if
(
!
isDebug
)
{
if
(
!
isDebug
)
{
pandaRecordWebSocketRef
.
current
.
wsClose
()
delayStartSocket
()
event
.
emit
(
"aiSound:finish"
,
{
event
.
emit
(
"aiSound:finish"
,
{
resultText
resultText
})
})
...
@@ -131,6 +161,14 @@ const Dialog = props => {
...
@@ -131,6 +161,14 @@ const Dialog = props => {
}
}
}
}
const
delayStartSocket
=
()
=>
{
pandaRecordWebSocketRef
.
current
.
wsClose
()
pandaRecordWebSocketRef
.
current
.
setStatus
(
"pause"
)
setTimeout
(()
=>
{
pandaRecordWebSocketRef
.
current
.
setStatus
(
"playing"
)
},
500
)
}
const
updateUserData
=
({
resultTextTemp
})
=>
{
const
updateUserData
=
({
resultTextTemp
})
=>
{
setData
(
data
=>
{
setData
(
data
=>
{
const
length
=
data
.
length
const
length
=
data
.
length
...
...
src/components/SoundAi/core/core/SpeechSynthesisUtterance/index.js
0 → 100644
View file @
dbf1cdfc
class
PandaSpeechSynthesisUtterance
{
constructor
(
options
=
{})
{
this
.
voiceParams
=
this
.
getVoiceParams
(
options
.
voiceParams
??
{})
this
.
data
=
[]
window
.
speechSynthesis
.
cancel
()
this
.
resolve
=
null
this
.
reject
=
null
this
.
onEnd
=
this
.
onEnd
.
bind
(
this
)
}
getVoiceParams
(
voiceParams
)
{
return
{
volume
:
1
,
rate
:
1
,
pitch
:
1
,
...
voiceParams
}
}
push
(
text
)
{
if
(
!
text
)
return
this
.
data
.
push
(
this
.
getSpeechSynthesisUtterance
(
text
))
window
.
speechSynthesis
.
speak
(
this
.
data
.
at
(
-
1
))
}
getSpeechSynthesisUtterance
(
text
)
{
const
speak
=
new
SpeechSynthesisUtterance
(
text
)
speak
.
addEventListener
(
"end"
,
this
.
onEnd
)
for
(
let
key
in
this
.
voiceParams
)
{
speak
[
key
]
=
this
.
voiceParams
[
key
]
}
return
speak
}
onEnd
()
{
this
.
data
.
shift
()
if
(
this
.
data
.
length
==
0
)
{
this
.
resolve
&&
this
.
resolve
()
}
}
speakEnd
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
this
.
resolve
=
resolve
this
.
reject
=
reject
})
}
clear
()
{
this
.
data
=
[]
window
.
speechSynthesis
.
cancel
()
}
}
export
default
PandaSpeechSynthesisUtterance
\ No newline at end of file
src/components/SoundAi/core/core/sockets/PandaRecordWebSocket.js
View file @
dbf1cdfc
...
@@ -121,6 +121,20 @@ class PandaRecordWebSocket extends PandaWebSocket {
...
@@ -121,6 +121,20 @@ class PandaRecordWebSocket extends PandaWebSocket {
this
.
recorderManager
.
onFrameRecorded
=
this
.
onRecorderFrameRecorded
;
this
.
recorderManager
.
onFrameRecorded
=
this
.
onRecorderFrameRecorded
;
}
}
pauseRecorederManager
()
{
if
(
this
.
recorderManager
)
{
this
.
recorderManager
.
stop
()
}
}
resumeRecorderManager
()
{
this
.
createRecorder
()
this
.
recorderManager
.
start
({
sampleRate
:
16000
,
frameSize
:
1280
,
})
}
onRecorderStart
(
e
)
{
onRecorderStart
(
e
)
{
this
.
recorderManager
.
status
=
'open'
;
this
.
recorderManager
.
status
=
'open'
;
this
.
events
.
recorderStart
();
this
.
events
.
recorderStart
();
...
...
src/components/SoundAi/core/core/sockets/PandaWebSocket.js
View file @
dbf1cdfc
...
@@ -66,7 +66,7 @@ class PandaWebSocket {
...
@@ -66,7 +66,7 @@ class PandaWebSocket {
wsClose
()
{
wsClose
()
{
if
(
this
.
ws
)
{
if
(
this
.
ws
)
{
this
.
ws
.
close
();
this
.
ws
.
close
(
1000
);
this
.
ws
=
null
;
this
.
ws
=
null
;
}
}
}
}
...
...
src/components/SoundAi/core/directive/CloseMenuDirective/index.js
View file @
dbf1cdfc
...
@@ -9,15 +9,17 @@ class CloseMenuDirective extends BaseDirective {
...
@@ -9,15 +9,17 @@ class CloseMenuDirective extends BaseDirective {
match
()
{
match
()
{
const
{
text
}
=
this
;
const
{
text
}
=
this
;
let
result
=
null
;
let
result
=
null
;
result
=
new
RegExp
(
`关闭(所有).*(?=(?:[
${
config
.
punctuationMark
}
]?))`
)
if
(
!
result
)
{
result
=
text
.
match
(
new
RegExp
(
`关闭(所有).*(?=(?:[
${
config
.
punctuationMark
}
]?))`
))
}
if
(
!
result
)
{
if
(
!
result
)
{
result
=
new
RegExp
(
`关闭(当前).*(?=(?:[
${
config
.
punctuationMark
}
]?))`
)
result
=
text
.
match
(
new
RegExp
(
`关闭(当前).*(?=(?:[
${
config
.
punctuationMark
}
]?))`
)
)
}
}
if
(
!
result
)
{
if
(
!
result
)
{
result
=
text
.
match
(
/关闭
(
.*
)(?=(?:
菜单|功能|路径
))
/
);
result
=
text
.
match
(
/关闭
(
.*
)(?=(?:
菜单|功能|路径
))
/
);
}
}
if
(
!
result
)
{
if
(
!
result
)
{
result
=
new
RegExp
(
`关闭(.*)(?=(?:[
${
config
.
punctuationMark
}
]?))`
)
result
=
text
.
match
(
new
RegExp
(
`关闭(.*)(?=(?:[
${
config
.
punctuationMark
}
]?))`
)
)
}
}
if
(
result
&&
result
.
length
>=
2
&&
!
this
.
matchResult
)
{
if
(
result
&&
result
.
length
>=
2
&&
!
this
.
matchResult
)
{
this
.
matchResult
=
result
[
1
];
this
.
matchResult
=
result
[
1
];
...
...
src/components/SoundAi/core/directive/OpenMenuDirective/index.js
View file @
dbf1cdfc
...
@@ -15,7 +15,7 @@ class OpenMenuDirective extends BaseDirective {
...
@@ -15,7 +15,7 @@ class OpenMenuDirective extends BaseDirective {
result
=
text
.
match
(
/打开
(
.*
)(?=(?:
菜单|功能|路径
))
/
)
result
=
text
.
match
(
/打开
(
.*
)(?=(?:
菜单|功能|路径
))
/
)
}
}
if
(
!
result
)
{
if
(
!
result
)
{
result
=
new
RegExp
(
`打开(.*)(?=(?:[
${
config
.
punctuationMark
}
]?))`
)
result
=
text
.
match
(
new
RegExp
(
`打开(.*)(?=(?:[
${
config
.
punctuationMark
}
]?))`
)
)
}
}
if
(
result
&&
result
.
length
>=
2
&&
!
this
.
matchResult
)
{
if
(
result
&&
result
.
length
>=
2
&&
!
this
.
matchResult
)
{
this
.
matchResult
=
result
[
1
]
this
.
matchResult
=
result
[
1
]
...
...
src/components/SoundAi/core/directive/TestDirective.js
View file @
dbf1cdfc
...
@@ -27,8 +27,14 @@ class TestDirective extends BaseDirective {
...
@@ -27,8 +27,14 @@ class TestDirective extends BaseDirective {
}
}
testCloseSession
({
sendMsg
})
{
testCloseSession
({
sendMsg
})
{
let
count
=
0
;
let
random
=
parseInt
(
Math
.
random
()
*
50
+
1
)
this
.
timer
=
setInterval
(()
=>
{
this
.
timer
=
setInterval
(()
=>
{
sendMsg
(
parseInt
(
Math
.
random
()
*
10
))
count
++
if
(
count
%
random
==
0
)
{
random
=
parseInt
(
Math
.
random
()
*
50
+
1
)
sendMsg
(
count
)
}
},
100
)
},
100
)
}
}
}
}
...
...
src/components/SoundAi/core/index.js
View file @
dbf1cdfc
...
@@ -7,6 +7,7 @@ import Directive , {DirectiveTypes, AllDirectiveTypes} from './directive';
...
@@ -7,6 +7,7 @@ import Directive , {DirectiveTypes, AllDirectiveTypes} from './directive';
import
AwakenDirective
from
'./directive/AwakenDirective'
;
import
AwakenDirective
from
'./directive/AwakenDirective'
;
import
ByeDirective
from
'./directive/ByeDirective'
;
import
ByeDirective
from
'./directive/ByeDirective'
;
import
CloseSessionDirective
from
'./directive/CloseSessionDirective'
;
import
CloseSessionDirective
from
'./directive/CloseSessionDirective'
;
import
PandaSpeechSynthesisUtterance
from
'./core/SpeechSynthesisUtterance'
;
export
{
export
{
RecorderManager
,
RecorderManager
,
...
@@ -19,5 +20,6 @@ export {
...
@@ -19,5 +20,6 @@ export {
ByeDirective
,
ByeDirective
,
DirectiveTypes
,
DirectiveTypes
,
AllDirectiveTypes
,
AllDirectiveTypes
,
CloseSessionDirective
CloseSessionDirective
,
PandaSpeechSynthesisUtterance
};
};
src/components/SoundAi/testCommand.js
View file @
dbf1cdfc
...
@@ -69,7 +69,11 @@ const testCommand = async () => {
...
@@ -69,7 +69,11 @@ const testCommand = async () => {
// });
// });
// await testFrameText("熊猫智慧水务解决方案是什么")
// await testFrameText("熊猫智慧水务解决方案是什么")
// await Utils.delayTime(6000)
// await Utils.delayTime(6000)
// await testFrameText("打开场景搭建功能菜单")
// await testFrameText(" 关闭当前他的。")
await
testFrameText
(
"今天武汉天气怎么样"
)
// await testFrameText("熊猫智慧水务解决方案是什么")
// await Utils.delayTime(6000)
// await testFrameText("我需要测试熊猫测试指令")
}
}
export
default
testCommand
export
default
testCommand
\ No newline at end of file
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