Add /:id/mp3 router to redirect request to speech MP3 URL

This commit is contained in:
Hongbo Wu 2022-08-16 22:17:30 +08:00
parent c74f2bc3fd
commit 301746d494
3 changed files with 60 additions and 10 deletions

View file

@ -3,15 +3,20 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import express from 'express'
import { CreateArticleErrorCode } from './../generated/graphql'
import { isSiteBlockedForParse } from './../utils/blocked'
import { CreateArticleErrorCode } from '../generated/graphql'
import { isSiteBlockedForParse } from '../utils/blocked'
import cors from 'cors'
import { buildLogger } from './../utils/logger'
import { buildLogger } from '../utils/logger'
import { corsConfig } from '../utils/corsConfig'
import { createPageSaveRequest } from '../services/create_page_save_request'
import { initModels } from '../server'
import { kx } from '../datalayer/knex_config'
import { getClaimsByToken } from '../utils/auth'
import * as jwt from 'jsonwebtoken'
import { env } from '../env'
import { Claims } from '../resolvers/types'
import { getRepository } from '../entity/utils'
import { Speech } from '../entity/speech'
const logger = buildLogger('app.dispatch')
@ -61,5 +66,40 @@ export function articleRouter() {
articleSavingRequestId: result.id,
})
})
router.get(
'/:id/mp3',
cors<express.Request>(corsConfig),
async (req, res) => {
const id = req.params.id
const token = req.cookies?.auth || req.headers?.authorization
if (!token || !jwt.verify(token, env.server.jwtSecret)) {
return res.status(401).send({ errorCode: 'UNAUTHORIZED' })
}
const { uid } = jwt.decode(token) as Claims
logger.info('Get article speech in mp3 format', {
params: req.params,
labels: {
userId: uid,
source: 'GetArticleSpeechMp3',
articleId: id,
},
})
const speech = await getRepository(Speech).findOneBy({
elasticPageId: id,
user: { id: uid },
})
if (!speech) {
return res.status(404).send({ errorCode: 'NOT_FOUND' })
}
logger.info('Found speech mp3', { audioUrl: speech.audioUrl })
res.redirect(speech.audioUrl)
}
)
return router
}

View file

@ -6,19 +6,20 @@ import { User } from '../../entity/user'
import { getPageById } from '../../elastic/pages'
import { synthesizeTextToSpeech } from '../../utils/textToSpeech'
import { Speech } from '../../entity/speech'
import { parseHTML } from 'linkedom'
export function textToSpeechServiceRouter() {
export function speechServiceRouter() {
const router = express.Router()
router.options('/', cors<express.Request>({ ...corsConfig, maxAge: 600 }))
// eslint-disable-next-line @typescript-eslint/no-misused-promises
router.post('/', async (req, res) => {
const { userId, pageId, text } = req.body as {
const { userId, pageId } = req.body as {
userId: string
pageId: string
text: string
}
if (!userId || !pageId || !text) {
if (!userId || !pageId) {
return res.status(200).send('Invalid data')
}
@ -35,7 +36,12 @@ export function textToSpeechServiceRouter() {
return res.status(200).send('Page not found')
}
const audioAndSpeechMarks = await synthesizeTextToSpeech({
const text = parseHTML(page.content).document.textContent
if (!text) {
return res.status(200).send('Page has no text')
}
const speech = await synthesizeTextToSpeech({
id: pageId,
text,
languageCode: page.language,
@ -44,11 +50,13 @@ export function textToSpeechServiceRouter() {
await getRepository(Speech).save({
elasticPageId: pageId,
audioUrl: audioAndSpeechMarks.audioUrl,
speechMarks: JSON.stringify(audioAndSpeechMarks.speechMarks),
audioUrl: speech.audioUrl,
speechMarks: JSON.stringify(speech.speechMarks),
user,
})
res.status(200).send('OK')
})
return router
}

View file

@ -45,6 +45,7 @@ import { uploadServiceRouter } from './routers/svc/upload'
import rateLimit from 'express-rate-limit'
import { webhooksServiceRouter } from './routers/svc/webhooks'
import { integrationsServiceRouter } from './routers/svc/integrations'
import { speechServiceRouter } from './routers/svc/speech'
const PORT = process.env.PORT || 4000
@ -119,6 +120,7 @@ export const createApp = (): {
app.use('/svc/pubsub/integrations', integrationsServiceRouter())
app.use('/svc/reminders', remindersServiceRouter())
app.use('/svc/pdf-attachments', pdfAttachmentsRouter())
app.use('/svc/speech', speechServiceRouter())
if (env.dev.isLocal) {
app.use('/local/debug', localDebugRouter())