get-video-info
Extract and display detailed information about a video file, such as format, duration, resolution, and codec, using a structured input path for analysis.
Instructions
Get detailed information about a video file
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| videoPath | Yes | Path to the video file to analyze |
Implementation Reference
- src/mcp-ffmpeg.ts:366-462 (handler)Handler function executes ffprobe to retrieve and format detailed video information including format, duration, size, bitrate, and stream details (video/audio). Includes file existence check, user permission via notification, and comprehensive error handling.async ({ videoPath }) => { try { // Resolve the absolute path const absVideoPath = path.resolve(videoPath); // Check if file exists try { await fs.access(absVideoPath); } catch (error) { return { isError: true, content: [{ type: "text" as const, text: `Error: Video file not found at ${absVideoPath}` }] }; } // Format command for permission request const permissionMessage = `Analyze video file ${path.basename(absVideoPath)}`; // Ask for permission const permitted = await askPermission(permissionMessage); if (!permitted) { return { isError: true, content: [{ type: "text" as const, text: "Permission denied by user" }] }; } // Build FFprobe command to get video information in JSON format const command = `ffprobe -v quiet -print_format json -show_format -show_streams "${absVideoPath}"`; // Execute FFprobe command const { stdout, stderr } = await execAsync(command); // Parse the JSON output const videoInfo = JSON.parse(stdout); // Format the output in a readable way let formattedInfo = `Video Information for: ${path.basename(absVideoPath)}\n\n`; // Format information if (videoInfo.format) { formattedInfo += `Format: ${videoInfo.format.format_name}\n`; formattedInfo += `Duration: ${videoInfo.format.duration} seconds\n`; formattedInfo += `Size: ${(parseInt(videoInfo.format.size) / (1024 * 1024)).toFixed(2)} MB\n`; formattedInfo += `Bitrate: ${(parseInt(videoInfo.format.bit_rate) / 1000).toFixed(2)} kbps\n\n`; } // Stream information if (videoInfo.streams && videoInfo.streams.length > 0) { formattedInfo += `Streams:\n`; videoInfo.streams.forEach((stream: any, index: number) => { formattedInfo += `\nStream #${index} (${stream.codec_type}):\n`; if (stream.codec_type === 'video') { formattedInfo += ` Codec: ${stream.codec_name}\n`; formattedInfo += ` Resolution: ${stream.width}x${stream.height}\n`; formattedInfo += ` Frame rate: ${stream.r_frame_rate}\n`; if (stream.bit_rate) { formattedInfo += ` Bitrate: ${(parseInt(stream.bit_rate) / 1000).toFixed(2)} kbps\n`; } } else if (stream.codec_type === 'audio') { formattedInfo += ` Codec: ${stream.codec_name}\n`; formattedInfo += ` Sample rate: ${stream.sample_rate} Hz\n`; formattedInfo += ` Channels: ${stream.channels}\n`; if (stream.bit_rate) { formattedInfo += ` Bitrate: ${(parseInt(stream.bit_rate) / 1000).toFixed(2)} kbps\n`; } } }); } return { content: [{ type: "text" as const, text: formattedInfo }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { isError: true, content: [{ type: "text" as const, text: `Error getting video information: ${errorMessage}` }] }; } } );
- src/mcp-ffmpeg.ts:363-365 (schema)Zod input schema defining 'videoPath' as a required string parameter with description.{ videoPath: z.string().describe("Path to the video file to analyze") },
- src/mcp-ffmpeg.ts:360-463 (registration)Registers the 'get-video-info' tool using McpServer.tool() method, specifying name, description, input schema, and handler function.server.tool( "get-video-info", "Get detailed information about a video file", { videoPath: z.string().describe("Path to the video file to analyze") }, async ({ videoPath }) => { try { // Resolve the absolute path const absVideoPath = path.resolve(videoPath); // Check if file exists try { await fs.access(absVideoPath); } catch (error) { return { isError: true, content: [{ type: "text" as const, text: `Error: Video file not found at ${absVideoPath}` }] }; } // Format command for permission request const permissionMessage = `Analyze video file ${path.basename(absVideoPath)}`; // Ask for permission const permitted = await askPermission(permissionMessage); if (!permitted) { return { isError: true, content: [{ type: "text" as const, text: "Permission denied by user" }] }; } // Build FFprobe command to get video information in JSON format const command = `ffprobe -v quiet -print_format json -show_format -show_streams "${absVideoPath}"`; // Execute FFprobe command const { stdout, stderr } = await execAsync(command); // Parse the JSON output const videoInfo = JSON.parse(stdout); // Format the output in a readable way let formattedInfo = `Video Information for: ${path.basename(absVideoPath)}\n\n`; // Format information if (videoInfo.format) { formattedInfo += `Format: ${videoInfo.format.format_name}\n`; formattedInfo += `Duration: ${videoInfo.format.duration} seconds\n`; formattedInfo += `Size: ${(parseInt(videoInfo.format.size) / (1024 * 1024)).toFixed(2)} MB\n`; formattedInfo += `Bitrate: ${(parseInt(videoInfo.format.bit_rate) / 1000).toFixed(2)} kbps\n\n`; } // Stream information if (videoInfo.streams && videoInfo.streams.length > 0) { formattedInfo += `Streams:\n`; videoInfo.streams.forEach((stream: any, index: number) => { formattedInfo += `\nStream #${index} (${stream.codec_type}):\n`; if (stream.codec_type === 'video') { formattedInfo += ` Codec: ${stream.codec_name}\n`; formattedInfo += ` Resolution: ${stream.width}x${stream.height}\n`; formattedInfo += ` Frame rate: ${stream.r_frame_rate}\n`; if (stream.bit_rate) { formattedInfo += ` Bitrate: ${(parseInt(stream.bit_rate) / 1000).toFixed(2)} kbps\n`; } } else if (stream.codec_type === 'audio') { formattedInfo += ` Codec: ${stream.codec_name}\n`; formattedInfo += ` Sample rate: ${stream.sample_rate} Hz\n`; formattedInfo += ` Channels: ${stream.channels}\n`; if (stream.bit_rate) { formattedInfo += ` Bitrate: ${(parseInt(stream.bit_rate) / 1000).toFixed(2)} kbps\n`; } } }); } return { content: [{ type: "text" as const, text: formattedInfo }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { isError: true, content: [{ type: "text" as const, text: `Error getting video information: ${errorMessage}` }] }; } } );