Skip to main content
Glama

mergeVideos

Combine multiple video files into one, with support for different formats and resolutions. This tool merges videos while intelligently adapting various inputs to create a unified output file.

Instructions

合并多个视频文件,支持不同格式和分辨率的智能适配

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
inputPathsYes输入视频文件路径数组
outputPathYes输出视频文件路径
qualityNo视频质量预设
videoCodecNo视频编码格式
audioCodecNo音频编码格式
resolutionNo目标分辨率
fpsNo目标帧率

Implementation Reference

  • Core handler implementing video merging: validates inputs, creates FFmpeg concat file list, sets up command with encoding options or copy, handles progress/cleanup and returns ProcessResult.
    public async mergeVideos(options: MergeOptions): Promise<ProcessResult> {
      const startTime = Date.now();
      const taskId = uuidv4();
    
      try {
        // 验证所有输入文件
        for (const inputPath of options.inputPaths) {
          await this.validateInputFile(inputPath);
        }
    
        // 确保输出目录存在
        await this.ensureOutputDir(options.outputPath);
    
        return new Promise(async (resolve, reject) => {
          try {
            // 创建临时文件列表
            const tempListPath = path.join(path.dirname(options.outputPath), `temp_list_${taskId}.txt`);
            const fileList = options.inputPaths.map(p => `file '${path.resolve(p).replace(/\\/g, '/')}'`).join('\n');
            await fs.writeFile(tempListPath, fileList, 'utf8');
    
            const command = ffmpeg()
              .input(tempListPath)
              .inputOptions(['-f', 'concat', '-safe', '0'])
              .output(options.outputPath);
    
            // 设置编码参数 - 避免使用复杂滤镜
            if (options.videoCodec || options.audioCodec) {
              // 需要重新编码
              command.outputOptions(['-c:v', options.videoCodec || 'libx264']);
              command.outputOptions(['-c:a', options.audioCodec || 'aac']);
              this.applyEncodingOptions(command, options);
            } else {
              // 使用流复制,更快更稳定
              command.outputOptions(['-c', 'copy']);
            }
    
            command.on('end', async () => {
              // 清理临时文件
              try {
                await fs.unlink(tempListPath);
              } catch (e) {
                console.warn('清理临时文件失败:', e);
              }
              
              resolve({
                success: true,
                outputPaths: [options.outputPath],
                duration: Date.now() - startTime
              });
            });
    
            command.on('error', async (err: any) => {
              // 清理临时文件
              try {
                await fs.unlink(tempListPath);
              } catch (e) {
                console.warn('清理临时文件失败:', e);
              }
              
              reject(new Error(`视频合并失败: ${err.message}`));
            });
    
            this.processingTasks.set(taskId, command);
            command.run();
            
          } catch (error) {
            reject(error);
          }
        });
    
      } catch (error) {
        return {
          success: false,
          outputPaths: [],
          duration: Date.now() - startTime,
          error: error instanceof Error ? error.message : '未知错误'
        };
      }
    }
  • MCP server wrapper handler for mergeVideos tool: delegates to VideoEngine.mergeVideos and formats response as MCP content.
    private async handleMergeVideos(args: MCPToolParams['mergeVideos']) {
      const result = await this.videoEngine.mergeVideos(args);
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(result, null, 2),
          },
        ],
      };
  • Registers the mergeVideos tool in MCP server's tool list with name, description, and detailed inputSchema.
    {
      name: 'mergeVideos',
      description: '合并多个视频文件,支持不同格式和分辨率的智能适配',
      inputSchema: {
        type: 'object',
        properties: {
          inputPaths: {
            type: 'array',
            items: { type: 'string' },
            description: '输入视频文件路径数组'
          },
          outputPath: {
            type: 'string',
            description: '输出视频文件路径'
          },
          quality: {
            type: 'string',
            enum: Object.values(QualityPreset),
            description: '视频质量预设'
          },
          videoCodec: {
            type: 'string',
            enum: Object.values(VideoCodec),
            description: '视频编码格式'
          },
          audioCodec: {
            type: 'string',
            enum: Object.values(AudioCodec),
            description: '音频编码格式'
          },
          resolution: {
            type: 'object',
            properties: {
              width: { type: 'number' },
              height: { type: 'number' }
            },
            description: '目标分辨率'
          },
          fps: {
            type: 'number',
            description: '目标帧率'
          }
        },
        required: ['inputPaths', 'outputPath']
      }
  • TypeScript interfaces defining input (MergeOptions) and output (ProcessResult) types for the mergeVideos tool.
    export interface MCPToolParams {
      // 视频剪辑工具参数
      clipVideo: ClipOptions;
      
      // 视频合并工具参数
      mergeVideos: MergeOptions;
      
      // 视频分割工具参数
      splitVideo: SplitOptions;
      
      // 获取视频信息工具参数
      getVideoInfo: {
        filePath: string;
      };
      
      // 批量处理工具参数
      batchProcess: {
        tasks: Omit<BatchTask, 'id' | 'status' | 'createdAt'>[];
      };
      
      // 获取支持格式工具参数
      getSupportedFormats: Record<string, never>;
      
      // 取消任务工具参数
      cancelTask: {
        taskId: string;
      };
      
      // 获取任务状态工具参数
      getTaskStatus: {
        taskId: string;
      };
    }
    
    // MCP工具返回值类型
    export interface MCPToolResults {
      clipVideo: ProcessResult;
      mergeVideos: ProcessResult;

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/pickstar-2002/video-clip-mcp'

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