Skip to main content
Glama
misbahsy

Video & Audio Editing MCP Server

by misbahsy

change_aspect_ratio

Modify video aspect ratio by cropping or adding padding with a specified color. Supports custom dimensions and outputs processed video to the desired path.

Instructions

Changes the aspect ratio of a video, using padding or cropping. Args listed in PRD. Returns: A status message indicating success or failure.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
output_video_pathYes
padding_colorNoblack
resize_modeNopad
target_aspect_ratioYes
video_pathYes

Implementation Reference

  • The main handler function for the 'change_aspect_ratio' tool. It uses FFmpeg to probe the video, calculate the target dimensions based on the desired aspect ratio, applies scaling, padding or cropping filters as specified, and outputs the processed video. Includes optimizations like codec copying where possible and fallbacks for re-encoding.
    @mcp.tool()
    def change_aspect_ratio(video_path: str, output_video_path: str, target_aspect_ratio: str, 
                              resize_mode: str = 'pad', padding_color: str = 'black') -> str:
        """Changes the aspect ratio of a video, using padding or cropping.
        Args listed in PRD.
        Returns:
            A status message indicating success or failure.
        """
        try:
            probe = ffmpeg.probe(video_path)
            video_stream_info = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
            if not video_stream_info:
                return "Error: No video stream found in the input file."
    
            original_width = int(video_stream_info['width'])
            original_height = int(video_stream_info['height'])
    
            num, den = map(int, target_aspect_ratio.split(':'))
            target_ar_val = num / den
            original_ar_val = original_width / original_height
    
            vf_filter = ""
            # Attempt to copy codecs if the operation doesn't strictly require re-encoding video stream
            # This is mostly for padding. Cropping implies re-encoding the video stream.
            codec_to_use = None 
    
            if resize_mode == 'pad':
                if abs(original_ar_val - target_ar_val) < 1e-4:
                    try:
                        ffmpeg.input(video_path).output(output_video_path, c='copy').run(capture_stdout=True, capture_stderr=True)
                        return f"Video aspect ratio already matches. Copied to {output_video_path}."
                    except ffmpeg.Error:
                         # If copy fails, just re-encode
                        ffmpeg.input(video_path).output(output_video_path).run(capture_stdout=True, capture_stderr=True)
                        return f"Video aspect ratio already matches. Re-encoded to {output_video_path}."
                
                if original_ar_val > target_ar_val: 
                    final_w = int(original_height * target_ar_val)
                    final_h = original_height
                    vf_filter = f"scale={final_w}:{final_h}:force_original_aspect_ratio=decrease,pad={final_w}:{final_h}:(ow-iw)/2:(oh-ih)/2:{padding_color}"
                else: 
                    final_w = original_width
                    final_h = int(original_width / target_ar_val)
                    vf_filter = f"scale={final_w}:{final_h}:force_original_aspect_ratio=decrease,pad={final_w}:{final_h}:(ow-iw)/2:(oh-ih)/2:{padding_color}"
                codec_to_use = 'copy' # Try to copy for padding, audio will be copied too
    
            elif resize_mode == 'crop':
                if abs(original_ar_val - target_ar_val) < 1e-4:
                    try:
                        ffmpeg.input(video_path).output(output_video_path, c='copy').run(capture_stdout=True, capture_stderr=True)
                        return f"Video aspect ratio already matches. Copied to {output_video_path}."
                    except ffmpeg.Error:
                        ffmpeg.input(video_path).output(output_video_path).run(capture_stdout=True, capture_stderr=True)
                        return f"Video aspect ratio already matches. Re-encoded to {output_video_path}."
                
                if original_ar_val > target_ar_val: 
                    new_width = int(original_height * target_ar_val)
                    vf_filter = f"crop={new_width}:{original_height}:(iw-{new_width})/2:0"
                else: 
                    new_height = int(original_width / target_ar_val)
                    vf_filter = f"crop={original_width}:{new_height}:0:(ih-{new_height})/2"
            else:
                return f"Error: Invalid resize_mode '{resize_mode}'. Must be 'pad' or 'crop'."
            
            try:
                # Try with specified video filter and copying audio codec
                ffmpeg.input(video_path).output(output_video_path, vf=vf_filter, acodec='copy').run(capture_stdout=True, capture_stderr=True)
                return f"Video aspect ratio changed (audio copy) to {target_aspect_ratio} using {resize_mode}. Saved to {output_video_path}"
            except ffmpeg.Error as e_acopy:
                # Fallback to re-encoding audio if audio copy failed
                try:
                    ffmpeg.input(video_path).output(output_video_path, vf=vf_filter).run(capture_stdout=True, capture_stderr=True)
                    return f"Video aspect ratio changed (audio re-encoded) to {target_aspect_ratio} using {resize_mode}. Saved to {output_video_path}"
                except ffmpeg.Error as e_recode_all:
                    err_acopy_msg = e_acopy.stderr.decode('utf8') if e_acopy.stderr else str(e_acopy)
                    err_recode_msg = e_recode_all.stderr.decode('utf8') if e_recode_all.stderr else str(e_recode_all)
                    return f"Error changing aspect ratio. Audio copy attempt failed: {err_acopy_msg}. Full re-encode attempt also failed: {err_recode_msg}."
    
        except ffmpeg.Error as e:
            error_message = e.stderr.decode('utf8') if e.stderr else str(e)
            return f"Error changing aspect ratio: {error_message}"
        except FileNotFoundError:
            return f"Error: Input video file not found at {video_path}"
        except ValueError:
            return f"Error: Invalid target_aspect_ratio format. Expected 'num:den' (e.g., '16:9')."
        except Exception as e:
            return f"An unexpected error occurred: {str(e)}"
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It mentions 'using padding or cropping' which gives some behavioral context about the transformation method, but doesn't disclose important traits like whether the operation is destructive (modifies original vs creates new file), what happens with invalid aspect ratios, performance characteristics, or error conditions. The return value description is minimal ('A status message indicating success or failure').

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief (3 sentences) but inefficiently structured. The first sentence is useful, but 'Args listed in PRD' wastes space without adding value for an AI agent. The return value sentence is minimal but could be more informative. While concise, it's not optimally front-loaded with the most critical information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a video transformation tool with 5 parameters, 0% schema coverage, no annotations, and no output schema, the description is inadequate. It doesn't explain parameter meanings, behavioral constraints, error handling, or provide examples. The mention of padding/cropping gives some context, but doesn't compensate for the missing structured information. The return value description is too vague to be helpful.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% (no parameter descriptions in schema), and the description explicitly states 'Args listed in PRD' rather than explaining parameters. This provides zero semantic information about the 5 parameters beyond what their names suggest. The description doesn't explain what target_aspect_ratio format should be, what resize_mode options exist, or what padding_color values are valid.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Changes the aspect ratio of a video, using padding or cropping.' This specifies both the action (change aspect ratio) and the resource (video), and distinguishes it from sibling tools like set_video_resolution or trim_video. However, it doesn't explicitly differentiate from all siblings (e.g., convert_video_properties might also affect aspect ratio).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites, when padding vs cropping is appropriate, or how it differs from related tools like set_video_resolution. The only contextual hint is 'using padding or cropping' which describes implementation rather than usage scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/misbahsy/video-audio-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server