feat: fix clouds functions and heygen
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import * as ImagePicker from 'expo-image-picker'
|
||||
import useMinuit from 'react-native-minuit/src/hooks/useMinuit.js'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import { Image, Text, View } from 'react-native'
|
||||
import { Image, Platform, Text, View } from 'react-native'
|
||||
import { background } from '../../assets'
|
||||
import ActivityLoader from '../../components/ActivityLoader'
|
||||
import BorderGradientButton from '../../components/BorderGradientButton'
|
||||
@@ -19,21 +19,50 @@ import { PLAYBACK_AI_STATUS } from '../../utils/playbackAi'
|
||||
import CreateLyricsHeader from '../Writing/components/CreateLyricsHeader'
|
||||
|
||||
const FUNCTIONS_REGION = 'europe-west1'
|
||||
const PHOTO_UPLOAD_TIMEOUT_MS = 120000
|
||||
const HEYGEN_START_TIMEOUT_MS = 60000
|
||||
|
||||
const trimString = (value) => (typeof value === 'string' ? value.trim() : '')
|
||||
|
||||
const isRemoteUrl = (value) => /^https?:\/\//i.test(trimString(value))
|
||||
|
||||
const resolveProject = ({ routeProject, selectedProject }) => {
|
||||
if (routeProject?.id && selectedProject?.id === routeProject.id) {
|
||||
if (routeProject && typeof routeProject === 'object' && routeProject.id) {
|
||||
if (selectedProject?.id === routeProject.id) {
|
||||
return selectedProject
|
||||
}
|
||||
|
||||
return routeProject
|
||||
}
|
||||
|
||||
if (selectedProject?.id) {
|
||||
return selectedProject
|
||||
}
|
||||
return routeProject || null
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const getInitialPhotoUri = ({ routePhotoUrl, project }) =>
|
||||
trimString(routePhotoUrl) || trimString(project?.playbackPhotoUrl) || null
|
||||
|
||||
const getImageExtension = (fileName) => {
|
||||
const normalizedFileName = trimString(fileName)
|
||||
const extension = normalizedFileName.includes('.')
|
||||
? normalizedFileName.split('.').pop().toLowerCase()
|
||||
: ''
|
||||
|
||||
return /^[a-z0-9]+$/.test(extension) ? extension : 'jpg'
|
||||
}
|
||||
|
||||
const withTimeout = (promise, timeoutMs, message) => {
|
||||
let timeoutId
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs)
|
||||
})
|
||||
|
||||
return Promise.race([promise, timeoutPromise]).finally(() => clearTimeout(timeoutId))
|
||||
}
|
||||
|
||||
const callStartPlaybackGeneration = (payload) => {
|
||||
const callable = getFunctionsClient(FUNCTIONS_REGION).httpsCallable('heygen-startPlaybackGeneration')
|
||||
return callable(payload)
|
||||
@@ -49,6 +78,7 @@ const PlaybackAi = ({ route }) => {
|
||||
project: resolveProject({ routeProject, selectedProject }),
|
||||
})
|
||||
)
|
||||
const [selectedPhotoAsset, setSelectedPhotoAsset] = useState(null)
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const project = useMemo(
|
||||
() => resolveProject({ routeProject, selectedProject }),
|
||||
@@ -64,9 +94,10 @@ const PlaybackAi = ({ route }) => {
|
||||
quality: 1,
|
||||
})
|
||||
|
||||
const nextUri = result?.assets?.[0]?.uri || null
|
||||
if (nextUri) {
|
||||
setSelectedPhotoUri(nextUri)
|
||||
const asset = result?.assets?.[0]
|
||||
if (asset?.uri) {
|
||||
setSelectedPhotoUri(asset.uri)
|
||||
setSelectedPhotoAsset(asset)
|
||||
}
|
||||
} catch (error) {
|
||||
setTooltip({
|
||||
@@ -77,6 +108,8 @@ const PlaybackAi = ({ route }) => {
|
||||
}
|
||||
|
||||
const handleGenerate = async () => {
|
||||
let step = 'validation'
|
||||
|
||||
try {
|
||||
if (!project?.id) {
|
||||
throw new Error('Projet introuvable')
|
||||
@@ -94,24 +127,46 @@ const PlaybackAi = ({ route }) => {
|
||||
|
||||
let photoUrl = trimString(selectedPhotoUri)
|
||||
if (!isRemoteUrl(photoUrl)) {
|
||||
const extension = trimString(selectedPhotoUri.split('.').pop()) || 'jpg'
|
||||
const uploadResult = await uploadFileToFirebase({
|
||||
uri: selectedPhotoUri,
|
||||
path: `users/${currentUID}/projects/${project.id}/heygen/photo-${Date.now()}.${extension}`,
|
||||
shouldCompress: true,
|
||||
fileType: 'IMAGE',
|
||||
step = 'photo_upload'
|
||||
const extension = getImageExtension(selectedPhotoAsset?.fileName)
|
||||
const path = `users/${currentUID}/projects/${project.id}/heygen/photo-${Date.now()}.${extension}`
|
||||
|
||||
console.log('[PlaybackAi] photo upload start', {
|
||||
path,
|
||||
fileSize: selectedPhotoAsset?.fileSize || null,
|
||||
platform: Platform.OS,
|
||||
})
|
||||
|
||||
const uploadResult = await withTimeout(
|
||||
uploadFileToFirebase({
|
||||
uri: selectedPhotoUri,
|
||||
path,
|
||||
shouldCompress: true,
|
||||
fileType: 'IMAGE',
|
||||
blob: Platform.OS === 'web' ? selectedPhotoAsset?.file : null,
|
||||
}),
|
||||
PHOTO_UPLOAD_TIMEOUT_MS,
|
||||
"L'envoi de la photo a dépassé 2 minutes. Vérifie ta connexion puis réessaie."
|
||||
)
|
||||
photoUrl = trimString(uploadResult?.resultURI)
|
||||
console.log('[PlaybackAi] photo upload complete', { path })
|
||||
}
|
||||
|
||||
if (!photoUrl) {
|
||||
throw new Error("Impossible d'envoyer la photo vers Firebase")
|
||||
}
|
||||
|
||||
await callStartPlaybackGeneration({
|
||||
projectId: project.id,
|
||||
photoUrl,
|
||||
})
|
||||
step = 'heygen_start'
|
||||
console.log('[PlaybackAi] HeyGen request start', { projectId: project.id })
|
||||
await withTimeout(
|
||||
callStartPlaybackGeneration({
|
||||
projectId: project.id,
|
||||
photoUrl,
|
||||
}),
|
||||
HEYGEN_START_TIMEOUT_MS,
|
||||
'HeyGen ne répond pas après 1 minute. Réessaie dans quelques instants.'
|
||||
)
|
||||
console.log('[PlaybackAi] HeyGen request accepted', { projectId: project.id })
|
||||
|
||||
navigate(Routes.PlaybackAiStatus, {
|
||||
project: {
|
||||
@@ -122,6 +177,11 @@ const PlaybackAi = ({ route }) => {
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('[PlaybackAi] generation failed', {
|
||||
step,
|
||||
code: error?.code,
|
||||
message: error?.message,
|
||||
})
|
||||
setTooltip({
|
||||
type: 'error',
|
||||
text: error?.message || 'Erreur lors du lancement du playback IA',
|
||||
|
||||
Reference in New Issue
Block a user