处理播放声音

This commit is contained in:
Xin Wang 2025-07-03 06:42:58 +08:00
parent c26b4558c8
commit b5ff2e7026
5 changed files with 97 additions and 18 deletions

View File

@ -63,12 +63,50 @@ export interface ScriptEpisode {
// 创建剧集
export const createScriptEpisode = async (data: CreateScriptEpisodeRequest): Promise<ApiResponse<ScriptEpisode>> => {
return post<ApiResponse<ScriptEpisode>>('/script_episode/create', data);
// return post<ApiResponse<ScriptEpisode>>('/script_episode/create', data);
return new Promise((resolve) => {
setTimeout(() => {
resolve({
code: 0,
message: 'success',
data: {
id: 1,
title: 'test',
script_id: 1,
status: 1,
episode_sort: 1,
creator_name: 'king',
created_at: '2025-07-03 10:00:00',
updated_at: '2025-07-03 10:00:00'
},
successful: true
});
}, 1000);
});
};
// 更新剧集
export const updateScriptEpisode = async (data: UpdateScriptEpisodeRequest): Promise<ApiResponse<ScriptEpisode>> => {
return post<ApiResponse<ScriptEpisode>>('/script_episode/update', data);
// return post<ApiResponse<ScriptEpisode>>('/script_episode/update', data);
return new Promise((resolve) => {
setTimeout(() => {
resolve({
code: 0,
message: 'success',
data: {
id: 1,
title: 'test',
script_id: 1,
status: 1,
episode_sort: 1,
creator_name: 'king',
created_at: '2025-07-03 10:00:00',
updated_at: '2025-07-03 10:00:00'
},
successful: true
});
}, 0);
});
};
// 获取剧集详情

View File

@ -72,7 +72,31 @@ export interface DeleteScriptProjectRequest {
// 创建剧本项目
export const createScriptProject = async (data: CreateScriptProjectRequest): Promise<ApiResponse<ScriptProject>> => {
return post<ApiResponse<ScriptProject>>('/script_project/create', data);
// return post<ApiResponse<ScriptProject>>('/script_project/create', data);
return new Promise((resolve) => {
setTimeout(() => {
resolve({
code: 0,
message: 'success',
data: {
id: 1,
title: '2025·07·03·001',
script_author: 'king',
characters: [],
summary: '',
project_type: 1,
status: 1,
cate_tags: [],
creator_name: 'king',
mode: 1,
resolution: 1,
created_at: '2025-07-03 10:00:00',
updated_at: '2025-07-03 10:00:00'
},
successful: true
});
}, 0);
});
};
// 获取剧本项目列表

View File

@ -60,7 +60,25 @@ export type ConvertScenePromptResponse = ApiResponse<ScenePrompts>;
export const convertScenePrompt = async (
request: ConvertScenePromptRequest
): Promise<ConvertScenePromptResponse> => {
return post<ConvertScenePromptResponse>('/video_flow/convert-scene-prompts', request);
// return post<ConvertScenePromptResponse>('/video_flow/convert-scene-prompts', request);
return new Promise((resolve) => {
setTimeout(() => {
resolve({
code: 0,
message: 'success',
data: {
scenes: [],
characters: [],
summary: '',
scene: '',
atmosphere: '',
episode_id: 0,
total_shots: ''
},
successful: true
});
}, 0);
});
};
/**

View File

@ -1,6 +1,6 @@
'use client'; // Add this to ensure it's a client component
import React, { useState } from 'react';
import React, { useState, useRef } from 'react';
import { Edit2, Trash2, Play, Volume2, VolumeX } from 'lucide-react';
import { Button } from '@/components/ui/button';
import dynamic from 'next/dynamic';
@ -20,6 +20,7 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP
const [hoveredId, setHoveredId] = useState<string | null>(null);
const [isPlaying, setIsPlaying] = useState<{ [key: string]: boolean }>({});
const [isMuted, setIsMuted] = useState<{ [key: string]: boolean }>({});
const videoRefs = useRef<{ [key: string]: HTMLVideoElement | null }>({});
const handleMouseEnter = (id: string) => {
setHoveredId(id);
@ -28,7 +29,7 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP
const handleMouseLeave = (id: string) => {
setHoveredId(null);
// 暂停视频并重新静音以便下次预览
const video = document.getElementById(`video-${id}`) as HTMLVideoElement;
const video = videoRefs.current[id];
if (video) {
video.pause();
video.muted = true;
@ -38,7 +39,7 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP
};
const togglePlay = (id: string) => {
const video = document.getElementById(`video-${id}`) as HTMLVideoElement;
const video = videoRefs.current[id];
if (video) {
if (video.paused) {
// 在用户主动播放时取消静音
@ -55,7 +56,7 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP
const toggleMute = (id: string, event: React.MouseEvent) => {
event.stopPropagation(); // 防止触发父元素的点击事件
const video = document.getElementById(`video-${id}`) as HTMLVideoElement;
const video = videoRefs.current[id];
if (video) {
video.muted = !video.muted;
setIsMuted(prev => ({ ...prev, [id]: video.muted }));
@ -74,7 +75,7 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP
{/* 视频容器 */}
<div className="relative aspect-video">
<video
id={`video-${video.id}`}
ref={(el) => (videoRefs.current[video.id] = el)}
src={video.url}
suppressHydrationWarning
className="w-full h-full object-cover"

View File

@ -18,14 +18,12 @@ function VideoScreenLayoutComponent({ videos }: VideoScreenLayoutProps) {
const [isAnimating, setIsAnimating] = useState(false);
const [isMuted, setIsMuted] = useState(true); // 默认静音
const containerRef = useRef<HTMLDivElement>(null);
const videoRefs = useRef<(HTMLVideoElement | null)[]>([]);
// 初始化时同步第一个视频的状态
// 确保视频refs数组长度与videos数组一致
useEffect(() => {
const currentVideo = document.getElementById(`video-screen-${currentIndex}`) as HTMLVideoElement;
if (currentVideo) {
setIsMuted(currentVideo.muted);
}
}, [currentIndex]);
videoRefs.current = videoRefs.current.slice(0, videos.length);
}, [videos.length]);
// 计算每个面板的样式
const getPanelStyle = (index: number) => {
@ -55,7 +53,7 @@ function VideoScreenLayoutComponent({ videos }: VideoScreenLayoutProps) {
// 切换静音状态
const toggleMute = () => {
const currentVideo = document.getElementById(`video-screen-${currentIndex}`) as HTMLVideoElement;
const currentVideo = videoRefs.current[currentIndex];
if (currentVideo) {
currentVideo.muted = !currentVideo.muted;
setIsMuted(currentVideo.muted);
@ -77,7 +75,7 @@ function VideoScreenLayoutComponent({ videos }: VideoScreenLayoutProps) {
setTimeout(() => {
setIsAnimating(false);
// 同步新视频的静音状态到UI
const newVideo = document.getElementById(`video-screen-${newIndex}`) as HTMLVideoElement;
const newVideo = videoRefs.current[newIndex];
if (newVideo) {
setIsMuted(newVideo.muted);
}
@ -104,7 +102,7 @@ function VideoScreenLayoutComponent({ videos }: VideoScreenLayoutProps) {
<div className="relative w-full h-full overflow-hidden rounded-lg">
{/* 视频 - Add suppressHydrationWarning to prevent className mismatch warnings */}
<video
id={`video-screen-${index}`}
ref={(el) => (videoRefs.current[index] = el)}
src={video.url}
suppressHydrationWarning
className="w-full h-full object-cover"