diff --git a/python_core/services/template_manager.py b/python_core/services/template_manager.py index b078a6d..b310fb0 100644 --- a/python_core/services/template_manager.py +++ b/python_core/services/template_manager.py @@ -56,10 +56,59 @@ class TemplateManager: def __init__(self): self.templates_dir = settings.temp_dir / "templates" self.templates_dir.mkdir(parents=True, exist_ok=True) - + # Template metadata file self.metadata_file = self.templates_dir / "templates.json" self.templates_metadata = self._load_metadata() + + @staticmethod + def detect_segment_type_from_path(file_path: str) -> str: + """根据文件路径的扩展名检测片段类型""" + if not file_path: + return 'video' # 默认类型 + + file_extension = file_path.lower().split('.')[-1] if '.' in file_path else '' + + # 视频格式 + video_extensions = { + 'mp4', 'avi', 'mov', 'mkv', 'wmv', 'flv', 'webm', 'm4v', '3gp', + 'ts', 'mts', 'mpg', 'mpeg', 'rm', 'rmvb', 'asf', 'divx' + } + + # 音频格式 + audio_extensions = { + 'mp3', 'wav', 'aac', 'flac', 'ogg', 'wma', 'm4a', 'opus', + 'ac3', 'dts', 'ape', 'aiff', 'au', 'ra' + } + + # 图片格式 + image_extensions = { + 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'tiff', + 'tga', 'ico', 'psd', 'raw', 'cr2', 'nef' + } + + # 文本/字幕格式 + text_extensions = { + 'txt', 'srt', 'ass', 'vtt', 'sub', 'ssa', 'lrc', 'sbv' + } + + # 特效格式 + effect_extensions = { + 'fx', 'effect', 'json', 'xml', 'preset' + } + + if file_extension in video_extensions: + return 'video' + elif file_extension in audio_extensions: + return 'audio' + elif file_extension in image_extensions: + return 'image' + elif file_extension in text_extensions: + return 'text' + elif file_extension in effect_extensions: + return 'effect' + else: + return 'video' # 默认为视频类型 def _load_metadata(self) -> Dict[str, Dict]: """Load templates metadata""" @@ -421,12 +470,12 @@ class TemplateManager: # Extract tracks and segments information tracks = [] if 'tracks' in draft_content: - for track_data in draft_content['tracks']: + for idx,track_data in enumerate(draft_content['tracks']): track = { 'id': track_data.get('id', ''), - 'name': track_data.get('name', f"Track {track_data.get('index', 0) + 1}"), - 'type': track_data.get('type', 'video'), - 'index': track_data.get('index', 0), + 'name': track_data.get('name', f""), + 'type': track_data.get('type', ''), + 'index': idx+1, 'segments': [], 'properties': track_data.get('properties', {}) } @@ -455,17 +504,16 @@ class TemplateManager: material_info = materials_lookup[material_id] resource_path = material_info['path'] material_name = material_info['name'] - # Auto-detect segment type from material type if not specified + # 根据resource_path后缀名 设置类型 if not segment_data.get('type'): segment_type = material_info['type'] + # 根据resource_path后缀名自动检测类型 + if resource_path and not segment_data.get('type'): + segment_type = TemplateManager.detect_segment_type_from_path(resource_path) + # Generate segment name based on material name or default - segment_name = segment_data.get('name', '') - if not segment_name: - if material_name: - segment_name = material_name - else: - segment_name = f'片段 {len(track["segments"]) + 1}' + segment_name = segment_data.get('name', '随机') segment = { 'id': segment_data.get('id', ''), diff --git a/src/components/timeline/TrackTimeline.tsx b/src/components/timeline/TrackTimeline.tsx index 09527a2..46230c7 100644 --- a/src/components/timeline/TrackTimeline.tsx +++ b/src/components/timeline/TrackTimeline.tsx @@ -2,7 +2,7 @@ import React from 'react' import { SegmentContextMenu } from './SegmentContextMenu' import { SegmentTooltip } from './SegmentTooltip' -interface TrackSegment { +export interface TrackSegment { id: string type: 'video' | 'audio' | 'image' | 'text' | 'effect' name: string @@ -13,11 +13,10 @@ interface TrackSegment { properties?: any effects?: any[] } - -interface Track { +export interface Track { id: string name: string - type: 'video' | 'audio' | 'subtitle' + type: 'video' | 'audio' | 'effect' | 'text' | 'sticker' | 'image' index: number segments: TrackSegment[] properties?: any @@ -159,7 +158,7 @@ export const TrackTimeline: React.FC = ({ {track.type === 'video' ? '视频' : track.type === 'audio' ? '音频' : '字幕'}

- 轨道 {track.index + 1}: {track.name} + {track.type}轨道 {track.index}: {track.name}

diff --git a/src/pages/TemplateDetailPage.tsx b/src/pages/TemplateDetailPage.tsx index a3cef6f..b5855b9 100644 --- a/src/pages/TemplateDetailPage.tsx +++ b/src/pages/TemplateDetailPage.tsx @@ -1,31 +1,10 @@ import React, { useState, useEffect } from 'react' import { useParams, useNavigate } from 'react-router-dom' -import { ArrowLeft, Play, Pause, RotateCcw, Trash2, ZoomIn, ZoomOut } from 'lucide-react' +import { ArrowLeft, RotateCcw, Trash2, ZoomIn, ZoomOut } from 'lucide-react' import { TemplateService } from '../services/tauri' import type { TemplateInfo } from '../hooks/useProgressCommand' import { TimelineRuler, TrackTimeline } from '../components/timeline' - -// 轨道和片段的数据结构 -interface TrackSegment { - id: string - type: 'video' | 'audio' | 'image' | 'text' | 'effect' - name: string - start_time: number - end_time: number - duration: number - resource_path?: string - properties?: any - effects?: any[] -} - -interface Track { - id: string - name: string - type: 'video' | 'audio' | 'subtitle' - index: number - segments: TrackSegment[] - properties?: any -} +import { Track } from '@/components/timeline/TrackTimeline' interface TemplateDetail { id: string @@ -46,7 +25,6 @@ const TemplateDetailPage: React.FC = () => { const [templateDetail, setTemplateDetail] = useState(null) const [loading, setLoading] = useState(true) const [currentTime, setCurrentTime] = useState(0) - const [isPlaying, setIsPlaying] = useState(false) const [timelineScale, setTimelineScale] = useState(100) // pixels per second useEffect(() => {