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
You need to sign in or sign up before continuing.
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