加入音频的人声分离和语音识别
parent
0252c4c34a
commit
6ccda55b92
|
|
@ -1,6 +1,6 @@
|
||||||
// API配置文件
|
// API配置文件
|
||||||
const API_CONFIG = {
|
const API_CONFIG = {
|
||||||
BASE_URL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000',
|
BASE_URL: "",
|
||||||
ENDPOINTS: {
|
ENDPOINTS: {
|
||||||
AUTH: {
|
AUTH: {
|
||||||
LOGIN: '/api/auth/login'
|
LOGIN: '/api/auth/login'
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ const CreateMeeting = ({ user }) => {
|
||||||
try {
|
try {
|
||||||
// Create meeting
|
// Create meeting
|
||||||
const meetingData = {
|
const meetingData = {
|
||||||
|
user_id: user.user_id,
|
||||||
title: formData.title,
|
title: formData.title,
|
||||||
meeting_time: formData.meeting_time || null,
|
meeting_time: formData.meeting_time || null,
|
||||||
attendee_ids: formData.attendees.map(a => a.user_id)
|
attendee_ids: formData.attendees.map(a => a.user_id)
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@ const EditMeeting = ({ user }) => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return `${API_BASE_URL}${response.data.url}`;
|
return `${API_BASE_URL}${response.data.file_path}`;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError('上传图片失败,请重试');
|
setError('上传图片失败,请重试');
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -441,6 +441,12 @@
|
||||||
background: #f8fafc;
|
background: #f8fafc;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border-left: 3px solid #667eea;
|
border-left: 3px solid #667eea;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcript-item:hover {
|
||||||
|
background-color: #f0f2ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transcript-header-item {
|
.transcript-header-item {
|
||||||
|
|
@ -456,21 +462,10 @@
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timestamp-button {
|
.timestamp {
|
||||||
background: #667eea;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
transition: all 0.3s ease;
|
color: #64748b;
|
||||||
}
|
|
||||||
|
|
||||||
.timestamp-button:hover {
|
|
||||||
background: #5a67d8;
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.transcript-text {
|
.transcript-text {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ const MeetingDetails = ({ user }) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// Fallback URL construction in case config fails
|
// Fallback URL construction in case config fails
|
||||||
const baseUrl = API_BASE_URL || 'http://localhost:8000';
|
const baseUrl = ""
|
||||||
const detailEndpoint = API_ENDPOINTS?.MEETINGS?.DETAIL?.(meeting_id) || `/api/meetings/${meeting_id}`;
|
const detailEndpoint = API_ENDPOINTS?.MEETINGS?.DETAIL?.(meeting_id) || `/api/meetings/${meeting_id}`;
|
||||||
const audioEndpoint = API_ENDPOINTS?.MEETINGS?.AUDIO?.(meeting_id) || `/api/meetings/${meeting_id}/audio`;
|
const audioEndpoint = API_ENDPOINTS?.MEETINGS?.AUDIO?.(meeting_id) || `/api/meetings/${meeting_id}/audio`;
|
||||||
const transcriptEndpoint = API_ENDPOINTS?.MEETINGS?.TRANSCRIPT?.(meeting_id) || `/api/meetings/${meeting_id}/transcript`;
|
const transcriptEndpoint = API_ENDPOINTS?.MEETINGS?.TRANSCRIPT?.(meeting_id) || `/api/meetings/${meeting_id}/transcript`;
|
||||||
|
|
@ -47,7 +47,7 @@ const MeetingDetails = ({ user }) => {
|
||||||
try {
|
try {
|
||||||
const audioResponse = await axios.get(`${baseUrl}${audioEndpoint}`);
|
const audioResponse = await axios.get(`${baseUrl}${audioEndpoint}`);
|
||||||
// Construct URL using uploads path and relative path from database
|
// Construct URL using uploads path and relative path from database
|
||||||
setAudioUrl(`${baseUrl}/uploads/${audioResponse.data.file_path}`);
|
setAudioUrl(`${baseUrl}${audioResponse.data.file_path}`);
|
||||||
setAudioFileName(audioResponse.data.file_name);
|
setAudioFileName(audioResponse.data.file_name);
|
||||||
} catch (audioError) {
|
} catch (audioError) {
|
||||||
console.warn('No audio file available:', audioError);
|
console.warn('No audio file available:', audioError);
|
||||||
|
|
@ -149,6 +149,8 @@ const MeetingDetails = ({ user }) => {
|
||||||
if (audioRef.current) {
|
if (audioRef.current) {
|
||||||
audioRef.current.currentTime = timestamp;
|
audioRef.current.currentTime = timestamp;
|
||||||
setCurrentTime(timestamp);
|
setCurrentTime(timestamp);
|
||||||
|
audioRef.current.play();
|
||||||
|
setIsPlaying(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -343,16 +345,17 @@ const MeetingDetails = ({ user }) => {
|
||||||
{showTranscript && (
|
{showTranscript && (
|
||||||
<div className="transcript-content">
|
<div className="transcript-content">
|
||||||
{transcript.map((item) => (
|
{transcript.map((item) => (
|
||||||
<div key={item.segment_id} className="transcript-item">
|
<div
|
||||||
|
key={item.segment_id}
|
||||||
|
className="transcript-item"
|
||||||
|
onClick={() => jumpToTime(item.start_time_ms / 1000)}
|
||||||
|
title="跳转到此时间点播放"
|
||||||
|
>
|
||||||
<div className="transcript-header-item">
|
<div className="transcript-header-item">
|
||||||
<span className="speaker-name">{item.speaker_tag}</span>
|
<span className="speaker-name">{item.speaker_tag}</span>
|
||||||
<button
|
<span className="timestamp">
|
||||||
className="timestamp-button"
|
|
||||||
onClick={() => jumpToTime(item.start_time_ms / 1000)}
|
|
||||||
title="跳转到此时间点"
|
|
||||||
>
|
|
||||||
{formatTime(item.start_time_ms / 1000)}
|
{formatTime(item.start_time_ms / 1000)}
|
||||||
</button>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="transcript-text">{item.text_content}</div>
|
<div className="transcript-text">{item.text_content}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,19 @@ import react from '@vitejs/plugin-react'
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
server: {
|
||||||
|
host: true, // Optional: Allows the server to be accessible externally
|
||||||
|
port: 5173, // Optional: Specify a port if needed
|
||||||
|
allowedHosts: ['c0e02ee.r9.cpolar.top'], // Add the problematic hostname here
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://localhost:8000', // 后端服务地址
|
||||||
|
changeOrigin: true, // 是否改变请求的源头
|
||||||
|
},
|
||||||
|
'/uploads': {
|
||||||
|
target: 'http://localhost:8000', // 后端服务地址
|
||||||
|
changeOrigin: true, // 是否改变请求的源头
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue