Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
C
CharIP-Electron
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
ali
CharIP-Electron
Commits
fe0d5ad2
Commit
fe0d5ad2
authored
Dec 26, 2023
by
ali
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 格式化
parent
229f45cf
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
80 additions
and
90 deletions
+80
-90
package.json
package.json
+1
-1
IPCs.ts
src/main/IPCs.ts
+1
-5
HeaderLayout.vue
src/renderer/components/layout/HeaderLayout.vue
+1
-1
HwWebRTC.ts
src/renderer/plugins/live/HwWebRTC.ts
+1
-1
PhotoRole.ts
src/renderer/plugins/live/PhotoRole.ts
+13
-14
ShowPhoto.vue
src/renderer/screens/ShowPhoto.vue
+21
-24
ShowVideo.vue
src/renderer/screens/ShowVideo.vue
+28
-30
jwt.ts
src/renderer/utils/jwt.ts
+14
-14
No files found.
package.json
View file @
fe0d5ad2
src/main/IPCs.ts
View file @
fe0d5ad2
...
@@ -45,11 +45,7 @@ export default class IPCs {
...
@@ -45,11 +45,7 @@ export default class IPCs {
// open new window
// open new window
ipcMain
.
on
(
ipcMain
.
on
(
'openWindow'
,
'openWindow'
,
async
(
async
(
event
,
url
:
string
,
options
:
BrowserWindowConstructorOptions
)
=>
{
event
,
url
:
string
,
options
:
BrowserWindowConstructorOptions
)
=>
{
const
ops
=
Object
.
assign
(
const
ops
=
Object
.
assign
(
{},
{},
{
{
...
...
src/renderer/components/layout/HeaderLayout.vue
View file @
fe0d5ad2
...
@@ -64,7 +64,7 @@ const asrItems = ref([
...
@@ -64,7 +64,7 @@ const asrItems = ref([
// 'Whisper Api'
// 'Whisper Api'
])
])
const
liveHosts
=
ref
([
const
liveHosts
=
ref
([
'laihua'
,
'laihua'
// 'http://111.229.216.162:9000',
// 'http://111.229.216.162:9000',
// 'http://124.221.182.173:9000',
// 'http://124.221.182.173:9000',
// 'http://110.42.214.59:9000',
// 'http://110.42.214.59:9000',
...
...
src/renderer/plugins/live/HwWebRTC.ts
View file @
fe0d5ad2
...
@@ -65,7 +65,7 @@ export class HwWebRTC extends EventEmitter {
...
@@ -65,7 +65,7 @@ export class HwWebRTC extends EventEmitter {
constructor
(
id
:
string
,
log
:
'none'
|
'error'
|
'warn'
|
'info'
|
'debug'
=
'none'
)
{
constructor
(
id
:
string
,
log
:
'none'
|
'error'
|
'warn'
|
'info'
|
'debug'
=
'none'
)
{
super
()
super
()
this
.
elementId
=
id
this
.
elementId
=
id
window
.
HWLLSPlayer
.
setLogLevel
(
log
)
;
window
.
HWLLSPlayer
.
setLogLevel
(
log
)
}
}
/**
/**
...
...
src/renderer/plugins/live/PhotoRole.ts
View file @
fe0d5ad2
/* eslint-disable camelcase */
/* eslint-disable camelcase */
import
http
,
{
axiosInstance
}
from
'@/renderer/utils/http'
import
http
,
{
axiosInstance
}
from
'@/renderer/utils/http'
import
{
JWT
}
from
'@/renderer/utils/jwt'
;
import
{
JWT
}
from
'@/renderer/utils/jwt'
import
{
HwWebRTC
}
from
'./HwWebRTC'
import
{
HwWebRTC
}
from
'./HwWebRTC'
import
{
guid
}
from
'@/renderer/utils/index'
import
{
guid
}
from
'@/renderer/utils/index'
import
EventEmitter
from
'EventEmitter'
import
EventEmitter
from
'EventEmitter'
...
@@ -21,10 +21,9 @@ type LiveOptions = {
...
@@ -21,10 +21,9 @@ type LiveOptions = {
}
}
type
SdkConfigDataParams
=
{
type
SdkConfigDataParams
=
{
baseUrl
:
string
;
baseUrl
:
string
baseSocketUrl
:
string
;
baseSocketUrl
:
string
};
}
export
class
PhotoAnswer
{
export
class
PhotoAnswer
{
question
=
''
question
=
''
...
@@ -462,7 +461,7 @@ export class PhotoRole extends EventEmitter {
...
@@ -462,7 +461,7 @@ export class PhotoRole extends EventEmitter {
this
.
_bindEvents
()
this
.
_bindEvents
()
if
(
this
.
host
===
'laihua'
)
{
if
(
this
.
host
===
'laihua'
)
{
this
.
host
=
await
this
.
auth
()
;
this
.
host
=
await
this
.
auth
()
}
}
await
this
.
initLive
()
await
this
.
initLive
()
...
@@ -473,19 +472,19 @@ export class PhotoRole extends EventEmitter {
...
@@ -473,19 +472,19 @@ export class PhotoRole extends EventEmitter {
const
token
=
JWT
.
encode
(
const
token
=
JWT
.
encode
(
JSON
.
stringify
({
appId
:
'88ca56ac88257f14'
,
iat
:
new
Date
().
getTime
()
+
1000
*
30
}),
JSON
.
stringify
({
appId
:
'88ca56ac88257f14'
,
iat
:
new
Date
().
getTime
()
+
1000
*
30
}),
'92b39dd13b952bcd4ce1995473cc3302'
'92b39dd13b952bcd4ce1995473cc3302'
)
;
)
axiosInstance
.
defaults
.
headers
.
common
.
Authorization
=
`Bearer
${
token
}
`
;
axiosInstance
.
defaults
.
headers
.
common
.
Authorization
=
`Bearer
${
token
}
`
const
res
=
await
http
({
url
:
'https://openapi.laihua.com/sdk/getConfig'
})
;
const
res
=
await
http
({
url
:
'https://openapi.laihua.com/sdk/getConfig'
})
const
{
code
,
data
}
=
res
as
{
const
{
code
,
data
}
=
res
as
{
code
:
number
|
string
;
code
:
number
|
string
data
:
SdkConfigDataParams
|
string
;
data
:
SdkConfigDataParams
|
string
}
;
}
if
(
code
!==
200
)
{
if
(
code
!==
200
)
{
throw
new
Error
(
`
${
code
}
:
${
JSON
.
stringify
(
res
)
}
`
);
throw
new
Error
(
`
${
code
}
:
${
JSON
.
stringify
(
res
)}
`
)
}
}
return
(
data
as
SdkConfigDataParams
).
baseUrl
;
return
(
data
as
SdkConfigDataParams
).
baseUrl
}
}
destroy
()
{
destroy
()
{
...
...
src/renderer/screens/ShowPhoto.vue
View file @
fe0d5ad2
...
@@ -61,11 +61,7 @@ async function init() {
...
@@ -61,11 +61,7 @@ async function init() {
return
return
}
}
if (
if (microphoneState.value === 'reply' && ans.playState === 'pause' && (await checkSteps())) {
microphoneState.value === 'reply' &&
ans.playState === 'pause' &&
await checkSteps()
) {
microphoneState.value = 'input'
microphoneState.value = 'input'
}
}
})
})
...
@@ -360,7 +356,6 @@ function initLLMSocket(): Promise<WebSocket> {
...
@@ -360,7 +356,6 @@ function initLLMSocket(): Promise<WebSocket> {
})
})
}
}
function endAudioInput() {
function endAudioInput() {
microphoneState.value = 'waitInput'
microphoneState.value = 'waitInput'
inputContext.mediaStream?.getTracks().forEach((track) => track.stop())
inputContext.mediaStream?.getTracks().forEach((track) => track.stop())
...
@@ -375,32 +370,34 @@ function endAudioInput() {
...
@@ -375,32 +370,34 @@ function endAudioInput() {
}
}
const answerArray: { text: string; isLast: boolean }[] = []
const answerArray: { text: string; isLast: boolean }[] = []
const steps: Promise<string>[] = []
;
const steps: Promise<string>[] = []
const checkSteps = async () => {
const checkSteps = async () => {
let count = 0
;
let count = 0
for (let i = 0; i < steps.length; i++) {
for (let i = 0; i < steps.length; i++) {
try {
try {
const res = await Promise.race([steps[i], new Promise((resolve) => setTimeout(() => resolve(false), 10))])
const res = await Promise.race([
if (res === false) continue;
steps[i],
new Promise((resolve) => setTimeout(() => resolve(false), 10))
])
if (res === false) continue
} catch (e) {
} catch (e) {
console.error(e)
console.error(e)
}
}
count
++;
count
++
if (count >= 2) {
if (count >= 2) {
return true
return true
}
}
}
}
return false
;
return false
}
}
const createStep = () => {
const createStep = () => {
let stepResolve: (string) => void = () => {}
;
let stepResolve: (string) => void = () => {}
let stepReject: (string) => void = () => {}
;
let stepReject: (string) => void = () => {}
const pose = new Promise<string>((resolve, reject) => {
const pose = new Promise<string>((resolve, reject) => {
stepResolve = resolve
;
stepResolve = resolve
stepReject = reject
;
stepReject = reject
})
})
return { pose, stepResolve, stepReject }
return { pose, stepResolve, stepReject }
...
@@ -418,9 +415,9 @@ async function onQ(question: string) {
...
@@ -418,9 +415,9 @@ async function onQ(question: string) {
let isTime = true
let isTime = true
let sliceAnswerLength = 10
let sliceAnswerLength = 10
answerArray.length = 0
answerArray.length = 0
steps.length = 0
;
steps.length = 0
const { pose, stepResolve, stepReject } = createStep()
;
const { pose, stepResolve, stepReject } = createStep()
steps.push(pose)
;
steps.push(pose)
photoRole!.answerArgs = new PhotoAnswer()
photoRole!.answerArgs = new PhotoAnswer()
ws.onmessage = (message) => {
ws.onmessage = (message) => {
...
@@ -437,7 +434,7 @@ async function onQ(question: string) {
...
@@ -437,7 +434,7 @@ async function onQ(question: string) {
runTTSTask(answerArray)
runTTSTask(answerArray)
inputContext.ws?.close()
inputContext.ws?.close()
console.log('----------------> answer: ', answer)
console.log('----------------> answer: ', answer)
stepResolve('chat')
;
stepResolve('chat')
return
return
}
}
...
@@ -474,8 +471,8 @@ async function runTTSTask(tasks: { text: string; isLast: boolean }[]) {
...
@@ -474,8 +471,8 @@ async function runTTSTask(tasks: { text: string; isLast: boolean }[]) {
if (isTTSRunning) return
if (isTTSRunning) return
isTTSRunning = true
isTTSRunning = true
const { pose, stepResolve, stepReject } = createStep()
;
const { pose, stepResolve, stepReject } = createStep()
steps.push(pose)
;
steps.push(pose)
try {
try {
while (tasks.length) {
while (tasks.length) {
...
...
src/renderer/screens/ShowVideo.vue
View file @
fe0d5ad2
...
@@ -263,11 +263,11 @@ function endAudioInput() {
...
@@ -263,11 +263,11 @@ function endAudioInput() {
inputContext
.
voskWs
.
send
(
'{"eof" : 1}'
)
inputContext
.
voskWs
.
send
(
'{"eof" : 1}'
)
inputContext
.
voskWs
.
close
()
inputContext
.
voskWs
.
close
()
}
}
ttsAudios
.
length
=
0
;
ttsAudios
.
length
=
0
inputContext
.
playingAudio
?.
pause
()
;
inputContext
.
playingAudio
?.
pause
()
videos
[
1
].
value
?.
pause
()
;
videos
[
1
].
value
?.
pause
()
videos
[
0
].
value
?.
pause
()
;
videos
[
0
].
value
?.
pause
()
isPlayRunning
=
false
;
isPlayRunning
=
false
}
}
const
canplay
=
()
=>
{
const
canplay
=
()
=>
{
...
@@ -286,7 +286,8 @@ function loadVideo(url: string) {
...
@@ -286,7 +286,8 @@ function loadVideo(url: string) {
}
}
async
function
qNLP
(
question
:
string
)
{
async
function
qNLP
(
question
:
string
)
{
const
resp
=
await
(
await
fetch
(
`
${
settings
.
nlpHost
}
/api/v1/generate`
,
{
const
resp
=
(
await
(
await
fetch
(
`
${
settings
.
nlpHost
}
/api/v1/generate`
,
{
headers
:
{
headers
:
{
accept
:
'application/json, text/plain, */*'
,
accept
:
'application/json, text/plain, */*'
,
'content-type'
:
'application/json'
'content-type'
:
'application/json'
...
@@ -296,15 +297,16 @@ async function qNLP(question: string) {
...
@@ -296,15 +297,16 @@ async function qNLP(question: string) {
}),
}),
method
:
'POST'
,
method
:
'POST'
,
mode
:
'cors'
mode
:
'cors'
})).
json
()
as
{
results
:
{
text
:
null
|
string
}[]
};
})
).
json
())
as
{
results
:
{
text
:
null
|
string
}[]
}
if
(
resp
.
results
[
0
].
text
===
null
)
return
''
;
if
(
resp
.
results
[
0
].
text
===
null
)
return
''
for
(
let
i
=
0
;
i
<
role
!
.
qa
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
role
!
.
qa
.
length
;
i
++
)
{
const
{
q
,
url
}
=
role
!
.
qa
[
i
]
const
{
q
,
url
}
=
role
!
.
qa
[
i
]
if
(
q
.
includes
(
resp
.
results
[
0
].
text
))
{
if
(
q
.
includes
(
resp
.
results
[
0
].
text
))
{
return
url
;
return
url
}
;
}
}
}
}
}
...
@@ -338,7 +340,7 @@ async function onQ(question: string) {
...
@@ -338,7 +340,7 @@ async function onQ(question: string) {
ws
.
onmessage
=
(
message
)
=>
{
ws
.
onmessage
=
(
message
)
=>
{
if
(
microphoneState
.
value
===
'input'
)
{
if
(
microphoneState
.
value
===
'input'
)
{
return
;
return
}
}
try
{
try
{
...
@@ -412,10 +414,9 @@ async function runTTSTask(tasks: string[]) {
...
@@ -412,10 +414,9 @@ async function runTTSTask(tasks: string[]) {
// @ts-ignore
// @ts-ignore
if
(
microphoneState
.
value
===
'input'
)
{
if
(
microphoneState
.
value
===
'input'
)
{
break
;
break
}
}
const
audio
=
new
Audio
(
`file://
${
res
[
0
].
text
}
`
)
const
audio
=
new
Audio
(
`file://
${
res
[
0
].
text
}
`
)
audio
.
load
()
audio
.
load
()
ttsAudios
.
push
(
audio
)
ttsAudios
.
push
(
audio
)
...
@@ -447,7 +448,7 @@ async function runAudioPlay() {
...
@@ -447,7 +448,7 @@ async function runAudioPlay() {
runAudioPlay
()
runAudioPlay
()
}
}
await
audio
.
play
()
await
audio
.
play
()
inputContext
.
playingAudio
=
audio
;
inputContext
.
playingAudio
=
audio
loadVideo
(
role
!
.
playUrl
)
loadVideo
(
role
!
.
playUrl
)
videos
[
1
].
value
!
.
loop
=
true
videos
[
1
].
value
!
.
loop
=
true
videos
[
1
].
value
!
.
muted
=
true
videos
[
1
].
value
!
.
muted
=
true
...
@@ -471,10 +472,10 @@ async function xfTTS(text: string) {
...
@@ -471,10 +472,10 @@ async function xfTTS(text: string) {
function
down
()
{
function
down
()
{
if
(
microphoneState
.
value
===
'reply'
)
{
if
(
microphoneState
.
value
===
'reply'
)
{
endAudioInput
()
;
endAudioInput
()
}
}
startVoskWsAudioInput
()
;
startVoskWsAudioInput
()
}
}
</
script
>
</
script
>
...
@@ -494,10 +495,7 @@ function down() {
...
@@ -494,10 +495,7 @@ function down() {
color=
"#fff"
color=
"#fff"
variant=
"elevated"
variant=
"elevated"
size=
"x-large"
size=
"x-large"
:disabled=
"
:disabled=
"microphoneState === 'loading' || microphoneState === 'disabled'"
microphoneState === 'loading' ||
microphoneState === 'disabled'
"
@
pointerdown=
"down"
@
pointerdown=
"down"
>
>
<v-icon
v-if=
"microphoneState === 'waitInput'"
icon=
"mdi-microphone"
></v-icon>
<v-icon
v-if=
"microphoneState === 'waitInput'"
icon=
"mdi-microphone"
></v-icon>
...
...
src/renderer/utils/jwt.ts
View file @
fe0d5ad2
import
CryptoJS
from
'crypto-js'
;
import
CryptoJS
from
'crypto-js'
export
class
JWT
{
export
class
JWT
{
static
sign
(
content
:
string
,
secret
:
string
)
{
static
sign
(
content
:
string
,
secret
:
string
)
{
const
r
=
CryptoJS
.
HmacSHA256
(
content
,
secret
)
;
const
r
=
CryptoJS
.
HmacSHA256
(
content
,
secret
)
const
b
=
CryptoJS
.
enc
.
Base64
.
stringify
(
r
)
;
const
b
=
CryptoJS
.
enc
.
Base64
.
stringify
(
r
)
return
this
.
base64urlEscape
(
b
)
;
return
this
.
base64urlEscape
(
b
)
}
}
static
base64urlEscape
(
str
:
string
)
{
static
base64urlEscape
(
str
:
string
)
{
return
str
.
replace
(
/
\+
/g
,
'-'
).
replace
(
/
\/
/g
,
'_'
).
replace
(
/=/g
,
''
)
;
return
str
.
replace
(
/
\+
/g
,
'-'
).
replace
(
/
\/
/g
,
'_'
).
replace
(
/=/g
,
''
)
}
}
static
toBase64
(
content
:
string
)
{
static
toBase64
(
content
:
string
)
{
return
btoa
(
content
)
;
return
btoa
(
content
)
}
}
static
encode
(
username
:
string
,
secret
:
string
)
{
static
encode
(
username
:
string
,
secret
:
string
)
{
const
header
=
this
.
toBase64
(
JSON
.
stringify
({
typ
:
'JWT'
,
alg
:
'HS256'
}))
;
const
header
=
this
.
toBase64
(
JSON
.
stringify
({
typ
:
'JWT'
,
alg
:
'HS256'
}))
const
content
=
this
.
toBase64
(
username
)
;
const
content
=
this
.
toBase64
(
username
)
const
sign
=
this
.
sign
([
header
,
content
].
join
(
'.'
),
secret
)
;
const
sign
=
this
.
sign
([
header
,
content
].
join
(
'.'
),
secret
)
return
[
header
,
content
,
sign
].
join
(
'.'
)
;
return
[
header
,
content
,
sign
].
join
(
'.'
)
}
}
static
decode
(
token
:
string
,
secret
:
string
)
{
static
decode
(
token
:
string
,
secret
:
string
)
{
const
[
header
,
content
,
sign
]
=
token
.
split
(
'.'
)
;
const
[
header
,
content
,
sign
]
=
token
.
split
(
'.'
)
const
newSign
=
this
.
sign
([
header
,
content
].
join
(
'.'
),
secret
)
;
const
newSign
=
this
.
sign
([
header
,
content
].
join
(
'.'
),
secret
)
if
(
sign
===
newSign
)
{
if
(
sign
===
newSign
)
{
return
atob
(
content
)
;
return
atob
(
content
)
}
else
{
}
else
{
throw
new
Error
(
'被篡改'
)
;
throw
new
Error
(
'被篡改'
)
}
}
}
}
}
}
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