get_video_info
Extract detailed video information such as format, resolution, duration, codec, and bitrate from video files to support analysis and conversion workflows.
Instructions
获取视频文件的详细信息,包括格式、分辨率、时长、编解码器、码率等。
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filePath | Yes | 视频文件的完整路径 |
Implementation Reference
- src/tools/info.ts:27-83 (handler)Main handler function for 'get_video_info' tool: validates input, fetches video info via FFmpegService, formats output with basic info, video/audio streams, and returns structured response.export async function handleGetVideoInfo(args: GetVideoInfoArgs): Promise<any> { const ffmpegService = FFmpegService.getInstance(); const validator = ValidatorService.getInstance(); try { // 验证输入文件 const validation = await validator.validateVideoFile(args.filePath); if (!validation.isValid) { return { success: false, error: `文件验证失败: ${validation.error}` }; } // 获取视频信息 console.log(`正在获取视频信息: ${args.filePath}`); const videoInfo = await ffmpegService.getVideoInfo(args.filePath); // 格式化输出信息 const formattedInfo = { 基本信息: { 文件路径: videoInfo.filePath, 文件格式: videoInfo.format, 文件大小: `${(videoInfo.size / (1024 * 1024)).toFixed(2)} MB`, 时长: formatDuration(videoInfo.duration) }, 视频流: videoInfo.video ? { 编解码器: videoInfo.video.codec, 分辨率: `${videoInfo.video.width} x ${videoInfo.video.height}`, 帧率: `${videoInfo.video.frameRate.toFixed(2)} fps`, 码率: (videoInfo.video.bitrate && videoInfo.video.bitrate > 0) ? `${Math.round(videoInfo.video.bitrate / 1000)} kbps` : '未知' } : null, 音频流: videoInfo.audio ? { 编解码器: videoInfo.audio.codec, 采样率: `${videoInfo.audio.sampleRate} Hz`, 声道数: videoInfo.audio.channels, 码率: (videoInfo.audio.bitrate && videoInfo.audio.bitrate > 0) ? `${Math.round(videoInfo.audio.bitrate / 1000)} kbps` : '未知' } : null }; return { success: true, message: '成功获取视频信息', data: { 原始信息: videoInfo, 格式化信息: formattedInfo } }; } catch (error: any) { console.error('获取视频信息失败:', error); return { success: false, error: `获取信息失败: ${error.message}` }; } }
- src/tools/info.ts:9-22 (schema)MCP Tool definition for 'get_video_info' including name, description, and JSON input schema requiring 'filePath'.export const getVideoInfoTool: Tool = { name: 'get_video_info', description: '获取视频文件的详细信息,包括格式、分辨率、时长、编解码器、码率等。', inputSchema: { type: 'object', properties: { filePath: { type: 'string', description: '视频文件的完整路径' } }, required: ['filePath'] } };
- src/tools/index.ts:22-26 (registration)Registration of tool handlers mapping 'get_video_info' to its handler function, used by MCP server for call_tool requests.export const toolHandlers = { convert_video: handleConvertVideo, get_video_info: handleGetVideoInfo, batch_convert: handleBatchConvert };
- src/tools/index.ts:15-19 (registration)List of all tools including getVideoInfoTool, used by MCP server for list_tools requests.export const tools = [ convertVideoTool, getVideoInfoTool, batchConvertTool ];
- src/services/ffmpeg.ts:29-97 (helper)FFmpegService.getVideoInfo: Core helper method using ffprobe to extract comprehensive video metadata including format, size, duration, video/audio streams details.async getVideoInfo(filePath: string): Promise<VideoInfo> { return new Promise((resolve, reject) => { ffmpeg.ffprobe(filePath, (err, metadata) => { if (err) { reject(new Error(`获取视频信息失败: ${err.message}`)); return; } try { const stats = statSync(filePath); const videoStream = metadata.streams.find(s => s.codec_type === 'video'); const audioStream = metadata.streams.find(s => s.codec_type === 'audio'); // 修复时长获取逻辑,特别是对WMV等格式 let duration = metadata.format.duration || 0; // 如果format中没有时长信息,尝试从视频流中获取 if (!duration || duration === 0) { if (videoStream && videoStream.duration) { duration = parseFloat(videoStream.duration); } else if (audioStream && audioStream.duration) { duration = parseFloat(audioStream.duration); } } // 如果还是没有时长,尝试通过帧数和帧率计算 if (!duration || duration === 0) { if (videoStream && videoStream.nb_frames && videoStream.r_frame_rate) { const frameCount = parseInt(videoStream.nb_frames); const frameRate = this.parseFrameRate(videoStream.r_frame_rate); if (frameCount > 0 && frameRate > 0) { duration = frameCount / frameRate; } } } const videoInfo: VideoInfo = { filePath, format: metadata.format.format_name || '未知', size: stats.size, duration: duration, }; if (videoStream) { videoInfo.video = { codec: videoStream.codec_name || '未知', width: videoStream.width || 0, height: videoStream.height || 0, frameRate: this.parseFrameRate(videoStream.r_frame_rate), bitrate: videoStream.bit_rate ? parseInt(videoStream.bit_rate) : null, }; } if (audioStream) { videoInfo.audio = { codec: audioStream.codec_name || '未知', sampleRate: audioStream.sample_rate || 0, channels: audioStream.channels || 0, bitrate: audioStream.bit_rate ? parseInt(audioStream.bit_rate) : null, }; } resolve(videoInfo); } catch (parseError) { reject(new Error(`解析视频信息失败: ${parseError}`)); } }); }); }