mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Call backend api to update speech in db
This commit is contained in:
parent
a8617f2605
commit
5a1dbb594e
3 changed files with 53 additions and 57 deletions
|
|
@ -9,11 +9,7 @@ import { getPageById } from '../../elastic/pages'
|
|||
import { Speech, SpeechState } from '../../entity/speech'
|
||||
import { buildLogger } from '../../utils/logger'
|
||||
import { getClaimsByToken } from '../../utils/auth'
|
||||
import {
|
||||
setSpeechFailure,
|
||||
shouldSynthesize,
|
||||
synthesize,
|
||||
} from '../../services/speech'
|
||||
import { shouldSynthesize, synthesize } from '../../services/speech'
|
||||
import { readPushSubscription } from '../../datalayer/pubsub'
|
||||
|
||||
const logger = buildLogger('app.dispatch')
|
||||
|
|
@ -79,58 +75,41 @@ export function speechServiceRouter() {
|
|||
router.options('/', cors<express.Request>({ ...corsConfig, maxAge: 600 }))
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
router.post('/', async (req, res) => {
|
||||
logger.info('Synthesize svc request', {
|
||||
logger.info('Updating speech', {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
body: req.body,
|
||||
})
|
||||
let userId: string
|
||||
const token = req.query.token as string
|
||||
try {
|
||||
if (!(await getClaimsByToken(token))) {
|
||||
const claims = await getClaimsByToken(token)
|
||||
if (!claims) {
|
||||
logger.info('Unauthorized request', { token })
|
||||
return res.status(200).send('UNAUTHORIZED')
|
||||
return res.status(401).send('UNAUTHORIZED')
|
||||
}
|
||||
userId = claims.uid
|
||||
} catch (error) {
|
||||
logger.error('Unauthorized request', { token, error })
|
||||
return res.status(200).send('UNAUTHORIZED')
|
||||
return res.status(401).send('UNAUTHORIZED')
|
||||
}
|
||||
|
||||
const { userId, speechId } = req.body as {
|
||||
userId: string
|
||||
const { speechId, audioFileName, speechMarksFileName } = req.body as {
|
||||
speechId: string
|
||||
audioFileName: string
|
||||
speechMarksFileName: string
|
||||
}
|
||||
if (!userId || !speechId) {
|
||||
return res.status(200).send('Invalid data')
|
||||
if (!speechId || !audioFileName || !speechMarksFileName) {
|
||||
return res.status(400).send('Invalid data')
|
||||
}
|
||||
|
||||
logger.info(`Create article speech`, {
|
||||
body: {
|
||||
userId,
|
||||
speechId,
|
||||
},
|
||||
labels: {
|
||||
source: 'CreateArticleSpeech',
|
||||
},
|
||||
// set state to completed
|
||||
await getRepository(Speech).update(speechId, {
|
||||
audioFileName: audioFileName,
|
||||
speechMarksFileName: speechMarksFileName,
|
||||
state: SpeechState.COMPLETED,
|
||||
})
|
||||
const speech = await getRepository(Speech).findOneBy({
|
||||
id: speechId,
|
||||
user: { id: userId },
|
||||
})
|
||||
if (!speech) {
|
||||
return res.status(200).send('Speech not found')
|
||||
}
|
||||
|
||||
const page = await getPageById(speech.elasticPageId)
|
||||
if (!page) {
|
||||
await setSpeechFailure(speech.id)
|
||||
return res.status(200).send('Page not found')
|
||||
}
|
||||
|
||||
try {
|
||||
await synthesize(page, speech)
|
||||
} catch (error) {
|
||||
logger.error(`Error synthesizing article`, { error })
|
||||
res.status(500).send('Error synthesizing article')
|
||||
}
|
||||
res.send('OK')
|
||||
})
|
||||
|
||||
return router
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@google-cloud/functions-framework": "3.1.2",
|
||||
"@google-cloud/pubsub": "^2.18.4",
|
||||
"@google-cloud/storage": "^6.4.1",
|
||||
"@sentry/serverless": "^6.16.1",
|
||||
"axios": "^0.27.2",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ import {
|
|||
SpeechSynthesisResult,
|
||||
SpeechSynthesizer,
|
||||
} from 'microsoft-cognitiveservices-speech-sdk'
|
||||
import { PubSub } from '@google-cloud/pubsub'
|
||||
import axios from 'axios'
|
||||
import * as jwt from 'jsonwebtoken'
|
||||
|
||||
interface TextToSpeechInput {
|
||||
id: string
|
||||
|
|
@ -43,8 +44,6 @@ interface SpeechMark {
|
|||
}
|
||||
|
||||
const storage = new Storage()
|
||||
const pubsub = new PubSub()
|
||||
const SPEECH_UPDATE_TOPIC = 'speech-update'
|
||||
|
||||
const uploadToBucket = async (
|
||||
filePath: string,
|
||||
|
|
@ -59,18 +58,25 @@ const createGCSFile = (bucket: string, filename: string): File => {
|
|||
return storage.bucket(bucket).file(filename)
|
||||
}
|
||||
|
||||
const updateSpeech = (
|
||||
const updateSpeech = async (
|
||||
speechId: string,
|
||||
audioFileName: string,
|
||||
speechMarksFileName: string
|
||||
): Promise<string | undefined> => {
|
||||
return pubsub
|
||||
.topic(SPEECH_UPDATE_TOPIC)
|
||||
.publishMessage({ json: { speechId, audioFileName, speechMarksFileName } })
|
||||
.catch((err) => {
|
||||
console.error('error publishing speech update:', err)
|
||||
return undefined
|
||||
})
|
||||
speechMarksFileName: string,
|
||||
token: string
|
||||
): Promise<boolean> => {
|
||||
if (!process.env.REST_BACKEND_ENDPOINT) {
|
||||
throw new Error('backend rest api endpoint not exists')
|
||||
}
|
||||
const response = await axios.post(
|
||||
`${process.env.REST_BACKEND_ENDPOINT}/svc/text-to-speech?token=${token}`,
|
||||
{
|
||||
speechId,
|
||||
audioFileName,
|
||||
speechMarksFileName,
|
||||
}
|
||||
)
|
||||
|
||||
return response.status === 200
|
||||
}
|
||||
|
||||
const synthesizeTextToSpeech = async (
|
||||
|
|
@ -375,17 +381,29 @@ const htmlElementToSsml = ({
|
|||
export const textToSpeechHandler = Sentry.GCPFunction.wrapHttpFunction(
|
||||
async (req, res) => {
|
||||
console.debug('New text to speech request', req)
|
||||
const token = req.query.token as string
|
||||
if (!process.env.JWT_SECRET) {
|
||||
console.error('JWT_SECRET not exists')
|
||||
return res.status(500).send('JWT_SECRET not exists')
|
||||
}
|
||||
try {
|
||||
jwt.verify(token, process.env.JWT_SECRET)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return res.status(200).send('UNAUTHENTICATED')
|
||||
}
|
||||
const input = req.body as TextToSpeechInput
|
||||
const { audioFileName, speechMarksFileName } = await synthesizeTextToSpeech(
|
||||
input
|
||||
)
|
||||
const result = await updateSpeech(
|
||||
const updated = await updateSpeech(
|
||||
input.id,
|
||||
audioFileName,
|
||||
speechMarksFileName
|
||||
speechMarksFileName,
|
||||
token
|
||||
)
|
||||
|
||||
if (!result) {
|
||||
if (!updated) {
|
||||
return res.status(500).send('Failed to update speech')
|
||||
}
|
||||
res.send('OK')
|
||||
|
|
|
|||
Loading…
Reference in a new issue