Fix voice clone: use absolute API URL for audio (not relative) so requests hit Render backend instead of Vercel SPA
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
|||||||
import { createAvatarVideoAsync } from '../../../../api/videoStudioApi';
|
import { createAvatarVideoAsync } from '../../../../api/videoStudioApi';
|
||||||
import { useVideoGenerationPolling } from '../../../../hooks/usePolling';
|
import { useVideoGenerationPolling } from '../../../../hooks/usePolling';
|
||||||
import { fetchMediaBlobUrl } from '../../../../utils/fetchMediaBlobUrl';
|
import { fetchMediaBlobUrl } from '../../../../utils/fetchMediaBlobUrl';
|
||||||
import { getAuthTokenGetter } from '../../../../api/client';
|
import { getAuthTokenGetter, getApiUrl } from '../../../../api/client';
|
||||||
import { VideoCameraFront, SkipNext, PlayArrow, InfoOutlined, Close as CloseIcon, HelpOutline, Refresh, RestartAlt, Undo } from '@mui/icons-material';
|
import { VideoCameraFront, SkipNext, PlayArrow, InfoOutlined, Close as CloseIcon, HelpOutline, Refresh, RestartAlt, Undo } from '@mui/icons-material';
|
||||||
import { VideoGenerationLoader } from '../../../shared/VideoGenerationLoader';
|
import { VideoGenerationLoader } from '../../../shared/VideoGenerationLoader';
|
||||||
import { OperationButton } from '../../../shared/OperationButton';
|
import { OperationButton } from '../../../shared/OperationButton';
|
||||||
@@ -49,8 +49,9 @@ export const TestPersonaModal: React.FC<TestPersonaModalProps> = ({
|
|||||||
if (tokenGetter) {
|
if (tokenGetter) {
|
||||||
const token = await tokenGetter();
|
const token = await tokenGetter();
|
||||||
if (token && !cancelled) {
|
if (token && !cancelled) {
|
||||||
const sep = voiceUrl.includes('?') ? '&' : '?';
|
const absoluteUrl = voiceUrl.startsWith('/') ? `${getApiUrl()}${voiceUrl}` : voiceUrl;
|
||||||
setAuthenticatedVoiceUrl(`${voiceUrl}${sep}token=${encodeURIComponent(token)}`);
|
const sep = absoluteUrl.includes('?') ? '&' : '?';
|
||||||
|
setAuthenticatedVoiceUrl(`${absoluteUrl}${sep}token=${encodeURIComponent(token)}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Box, Typography, Paper, Stack, Button, Alert, TextField, CircularProgre
|
|||||||
import { keyframes } from '@mui/system';
|
import { keyframes } from '@mui/system';
|
||||||
import { Mic, GraphicEq, Timer, CloudUpload, Stop, PlayArrow, InfoOutlined, TextFields, HelpOutline, AutoAwesome, Campaign, MicNone, Podcasts, RestartAlt, Undo, Headphones, Article, VideoLibrary, TrendingUp, CheckCircle, RecordVoiceOver, Settings } from '@mui/icons-material';
|
import { Mic, GraphicEq, Timer, CloudUpload, Stop, PlayArrow, InfoOutlined, TextFields, HelpOutline, AutoAwesome, Campaign, MicNone, Podcasts, RestartAlt, Undo, Headphones, Article, VideoLibrary, TrendingUp, CheckCircle, RecordVoiceOver, Settings } from '@mui/icons-material';
|
||||||
import { createVoiceClone, createVoiceDesign, getLatestVoiceClone, setBrandVoice } from '../../../../api/brandAssets';
|
import { createVoiceClone, createVoiceDesign, getLatestVoiceClone, setBrandVoice } from '../../../../api/brandAssets';
|
||||||
import { getAuthTokenGetter } from '../../../../api/client';
|
import { getAuthTokenGetter, getApiUrl } from '../../../../api/client';
|
||||||
import { OperationButton } from '../../../shared/OperationButton';
|
import { OperationButton } from '../../../shared/OperationButton';
|
||||||
|
|
||||||
const pulse = keyframes`
|
const pulse = keyframes`
|
||||||
@@ -114,8 +114,9 @@ export const VoiceAvatarPlaceholder: React.FC<{ domainName?: string; onVoiceSet?
|
|||||||
const token = await tokenGetter();
|
const token = await tokenGetter();
|
||||||
console.log('[VoiceClone] Got token:', token ? 'yes' : 'no');
|
console.log('[VoiceClone] Got token:', token ? 'yes' : 'no');
|
||||||
if (token && !cancelled) {
|
if (token && !cancelled) {
|
||||||
const sep = resultAudioUrl.includes('?') ? '&' : '?';
|
const absoluteUrl = resultAudioUrl.startsWith('/') ? `${getApiUrl()}${resultAudioUrl}` : resultAudioUrl;
|
||||||
const authUrl = `${resultAudioUrl}${sep}token=${encodeURIComponent(token)}`;
|
const sep = absoluteUrl.includes('?') ? '&' : '?';
|
||||||
|
const authUrl = `${absoluteUrl}${sep}token=${encodeURIComponent(token)}`;
|
||||||
console.log('[VoiceClone] Setting authenticatedAudioUrl:', authUrl);
|
console.log('[VoiceClone] Setting authenticatedAudioUrl:', authUrl);
|
||||||
setAuthenticatedAudioUrl(authUrl);
|
setAuthenticatedAudioUrl(authUrl);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import {
|
|||||||
Category,
|
Category,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import { getLatestVoiceClone, VoiceCloneResponse } from "../../api/brandAssets";
|
import { getLatestVoiceClone, VoiceCloneResponse } from "../../api/brandAssets";
|
||||||
import { getAuthTokenGetter } from "../../api/client";
|
import { getAuthTokenGetter, getApiUrl } from "../../api/client";
|
||||||
import { VoiceAvatarPlaceholder } from "../OnboardingWizard/PersonalizationStep/components/VoiceAvatarPlaceholder";
|
import { VoiceAvatarPlaceholder } from "../OnboardingWizard/PersonalizationStep/components/VoiceAvatarPlaceholder";
|
||||||
|
|
||||||
export type VoiceOption = {
|
export type VoiceOption = {
|
||||||
@@ -250,6 +250,10 @@ export const VoiceSelector: React.FC<VoiceSelectorProps> = ({
|
|||||||
|
|
||||||
// Append auth token for endpoints that require it (e.g. /api/assets/)
|
// Append auth token for endpoints that require it (e.g. /api/assets/)
|
||||||
let previewUrl = voice.previewUrl;
|
let previewUrl = voice.previewUrl;
|
||||||
|
// Convert relative URLs to absolute (pointing to backend, not Vercel)
|
||||||
|
if (previewUrl.startsWith('/')) {
|
||||||
|
previewUrl = `${getApiUrl()}${previewUrl}`;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const tokenGetter = getAuthTokenGetter();
|
const tokenGetter = getAuthTokenGetter();
|
||||||
if (tokenGetter) {
|
if (tokenGetter) {
|
||||||
|
|||||||
Reference in New Issue
Block a user