Skip to main content
Glama
bitscorp-mcp

MCP FFmpeg Video Processor

by bitscorp-mcp

extract-audio

Extract audio from video files in MP3, AAC, WAV, or OGG format using the MCP FFmpeg Video Processor. Convert video to audio by specifying input path and desired format.

Instructions

Extract audio from a video file

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
videoPathYesPath to the video file to extract audio from
formatNoAudio format to extractmp3
outputDirNoOptional directory to save the output file (defaults to a temporary directory)

Implementation Reference

  • The handler function for the 'extract-audio' tool. It resolves paths, checks file existence and permissions, requests user permission, determines audio codec based on format, executes FFmpeg command to extract audio without video (-vn -acodec), and returns success or error response.
    async ({ videoPath, format, outputDir }) => {
      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}`
            }]
          };
        }
    
        // Determine output directory
        let outputDirectory = outputDir ? path.resolve(outputDir) : await ensureDirectoriesExist();
    
        // Check if output directory exists and is writable
        try {
          await fs.access(outputDirectory, fs.constants.W_OK);
        } catch (error) {
          return {
            isError: true,
            content: [{
              type: "text" as const,
              text: `Error: Output directory ${outputDirectory} does not exist or is not writable`
            }]
          };
        }
    
        // Format command for permission request
        const permissionMessage = `Extract ${format} audio from video ${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"
            }]
          };
        }
    
        // Get video filename without extension
        const videoFilename = path.basename(absVideoPath, path.extname(absVideoPath));
        const outputFilename = `${videoFilename}.${format}`;
        const outputPath = path.join(outputDirectory, outputFilename);
    
        // Determine audio codec based on format
        let audioCodec;
        switch (format) {
          case 'mp3':
            audioCodec = 'libmp3lame';
            break;
          case 'aac':
            audioCodec = 'aac';
            break;
          case 'wav':
            audioCodec = 'pcm_s16le';
            break;
          case 'ogg':
            audioCodec = 'libvorbis';
            break;
          default:
            audioCodec = 'libmp3lame';
        }
    
        // Build FFmpeg command
        const command = `ffmpeg -i "${absVideoPath}" -vn -acodec ${audioCodec} "${outputPath}"`;
    
        try {
          // Execute FFmpeg command
          const { stdout, stderr } = await execAsync(command);
    
          return {
            content: [{
              type: "text" as const,
              text: `Successfully extracted audio to: ${outputPath}`
            }]
          };
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : String(error);
          return {
            isError: true,
            content: [{
              type: "text" as const,
              text: `Error extracting audio: ${errorMessage}`
            }]
          };
        }
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        return {
          isError: true,
          content: [{
            type: "text" as const,
            text: `Error extracting audio: ${errorMessage}`
          }]
        };
      }
    }
  • Input schema using Zod for the 'extract-audio' tool, defining videoPath (required string), format (enum mp3|aac|wav|ogg, default mp3), outputDir (optional string).
    {
      videoPath: z.string().describe("Path to the video file to extract audio from"),
      format: z.enum(["mp3", "aac", "wav", "ogg"]).default("mp3").describe("Audio format to extract"),
      outputDir: z.string().optional().describe("Optional directory to save the output file (defaults to a temporary directory)")
    },
  • Registration of the 'extract-audio' tool on the MCP server using server.tool(), specifying name, description, input schema, and handler function.
    server.tool(
      "extract-audio",
      "Extract audio from a video file",
      {
        videoPath: z.string().describe("Path to the video file to extract audio from"),
        format: z.enum(["mp3", "aac", "wav", "ogg"]).default("mp3").describe("Audio format to extract"),
        outputDir: z.string().optional().describe("Optional directory to save the output file (defaults to a temporary directory)")
      },
      async ({ videoPath, format, outputDir }) => {
        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}`
              }]
            };
          }
    
          // Determine output directory
          let outputDirectory = outputDir ? path.resolve(outputDir) : await ensureDirectoriesExist();
    
          // Check if output directory exists and is writable
          try {
            await fs.access(outputDirectory, fs.constants.W_OK);
          } catch (error) {
            return {
              isError: true,
              content: [{
                type: "text" as const,
                text: `Error: Output directory ${outputDirectory} does not exist or is not writable`
              }]
            };
          }
    
          // Format command for permission request
          const permissionMessage = `Extract ${format} audio from video ${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"
              }]
            };
          }
    
          // Get video filename without extension
          const videoFilename = path.basename(absVideoPath, path.extname(absVideoPath));
          const outputFilename = `${videoFilename}.${format}`;
          const outputPath = path.join(outputDirectory, outputFilename);
    
          // Determine audio codec based on format
          let audioCodec;
          switch (format) {
            case 'mp3':
              audioCodec = 'libmp3lame';
              break;
            case 'aac':
              audioCodec = 'aac';
              break;
            case 'wav':
              audioCodec = 'pcm_s16le';
              break;
            case 'ogg':
              audioCodec = 'libvorbis';
              break;
            default:
              audioCodec = 'libmp3lame';
          }
    
          // Build FFmpeg command
          const command = `ffmpeg -i "${absVideoPath}" -vn -acodec ${audioCodec} "${outputPath}"`;
    
          try {
            // Execute FFmpeg command
            const { stdout, stderr } = await execAsync(command);
    
            return {
              content: [{
                type: "text" as const,
                text: `Successfully extracted audio to: ${outputPath}`
              }]
            };
          } catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            return {
              isError: true,
              content: [{
                type: "text" as const,
                text: `Error extracting audio: ${errorMessage}`
              }]
            };
          }
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : String(error);
          return {
            isError: true,
            content: [{
              type: "text" as const,
              text: `Error extracting audio: ${errorMessage}`
            }]
          };
        }
      }
    );
  • Helper function to request user permission via desktop notification before executing FFmpeg operations, used by extract-audio handler.
    async function askPermission(action: string): Promise<boolean> {
      // Skip notification if DISABLE_NOTIFICATIONS is set
      if (process.env.DISABLE_NOTIFICATIONS === 'true') {
        console.log(`Auto-allowing action (notifications disabled): ${action}`);
        return true;
      }
    
      return new Promise((resolve) => {
        notifier.notify({
          title: 'FFmpeg Processor Permission Request',
          message: `${action}`,
          wait: true,
          timeout: 60,
          actions: 'Allow',
          closeLabel: 'Deny'
        }, (err, response, metadata) => {
          if (err) {
            console.error('Error showing notification:', err);
            resolve(false);
            return;
          }
    
          const buttonPressed = metadata?.activationValue || response;
          resolve(buttonPressed !== 'Deny');
        });
      });
    }
  • Helper function to ensure output directory exists in temp folder, used by extract-audio to determine output path.
    async function ensureDirectoriesExist() {
      const outputDir = path.join(os.tmpdir(), 'ffmpeg-output');
      try {
        await fs.mkdir(outputDir, { recursive: true });
        return outputDir;
      } catch (error) {
        console.error('Error creating output directory:', error);
        return os.tmpdir();
      }
    }

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/bitscorp-mcp/mcp-ffmpeg'

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