FFmpeg 错误:无法在过滤器 Parsed_amix_54 上找到未标记的输入板 0 的匹配流

问题描述 投票:0回答:1

我正在开发一个使用 React.js 和 FFmpeg 生成点击轨迹的项目。该项目包括一个 Express.js 后端,我在其中构建了一个 FFmpeg 命令,将多个音频文件(倒数、声音提示和点击声)合并到一个轨道中。最终输出应该是 MP3 文件。

但是,我在运行 FFmpeg 命令时遇到错误:

Cannot find a matching stream for unlabeled input pad 0 on filter Parsed_amix_54

如何正确构建 FFmpeg 命令以避免“找不到未标记输入板的匹配流”错误并确保所有输入都得到正确处理和混合?

这是我的server.js代码的相关部分:

const express = require('express');
const bodyParser = require('body-parser');
const { exec } = require('child_process');
const path = require('path');
const fs = require('fs');
const ffmpegPath = require('ffmpeg-static');
const cors = require('cors');

const app = express();
app.use(cors());
app.use(bodyParser.json());

app.post('/generate-click-track', (req, res) => {
    const { tempo, timeSignature, clickSound, subdivisions, sections } = req.body;
    const clickSoundPath = path.join(__dirname, 'public', 'click-sounds');
    const vocalCuesPath = path.join(__dirname, 'public', 'vocal-cues');

    const beatsPerBar = parseInt(timeSignature.split('/')[0]);
    const beatsPerMinute = tempo;
    let totalBeats = 0;
    const sectionStarts = [];

    sections.forEach((section, index) => {
        if (index > 0) {
            sectionStarts.push(totalBeats);
        }
        totalBeats += section.length * beatsPerBar;
    });

    const outputFilePath = path.join(__dirname, 'output', 'click-track.mp3');
    const tempDir = path.join(__dirname, 'temp');

    if (!fs.existsSync(tempDir)) {
        fs.mkdirSync(tempDir);
    }

    const countInFiles = Array.from({ length: beatsPerBar }, (_, i) => path.join(vocalCuesPath, 'count-ins', `${i + 1}.wav`));

    let ffmpegCommand = '';

    // Add count-in files
    countInFiles.forEach(file => {
        ffmpegCommand += `-i "${file}" `;
    });

    // Add section vocal cues and click sounds
    sections.forEach((section, index) => {
        const vocalCueFile = path.join(vocalCuesPath, `${section.name}.wav`);
        ffmpegCommand += `-i "${vocalCueFile}" `;

        for (let i = 0; i < section.length * beatsPerBar; i++) {
            const clickFile = i % beatsPerBar === 0 ? `${clickSound}-accents.mp3` : `${clickSound}.mp3`;
            ffmpegCommand += `-i "${path.join(clickSoundPath, clickFile)}" `;
        }
    });

    ffmpegCommand += `-filter_complex "`;

    let inputCount = 0;
    countInFiles.forEach((_, index) => {
        ffmpegCommand += `[${inputCount}:0]adelay=${index * (60 / beatsPerMinute) * 1000}|${index * (60 / beatsPerMinute) * 1000}[a${inputCount}]; `;
        inputCount++;
    });

    sections.forEach((section, index) => {
        const delay = (sectionStarts[index] ? sectionStarts[index] : 0) * (60 / beatsPerMinute) * 1000;
        ffmpegCommand += `[${inputCount}:0]adelay=${delay}|${delay}[a${inputCount}]; `;
        inputCount++;

        for (let i = 0; i < section.length * beatsPerBar; i++) {
            const delay = (sectionStarts[index] ? sectionStarts[index] : 0) * (60 / beatsPerMinute) * 1000 + (i * 60 / beatsPerMinute) * 1000;
            ffmpegCommand += `[${inputCount}:0]adelay=${delay}|${delay}[a${inputCount}]; `;
            inputCount++;
        }
    });

    ffmpegCommand += `amix=inputs=${inputCount}:duration=longest" -codec:a libmp3lame -b:a 192k -y "${outputFilePath}"`;

    console.log(`Executing ffmpeg command: ${ffmpegCommand}`);

    exec(`${ffmpegPath} ${ffmpegCommand}`, (error, stdout, stderr) => {
        if (error) {
            console.error(`Error generating click track: ${error.message}`);
            res.status(500).send('Error generating click track');
            return;
        }

        res.download(outputFilePath, 'click-track.mp3', (err) => {
            if (err) {
                console.error(`Error sending file: ${err.message}`);
            }

            // Clean up temp directory
            fs.readdir(tempDir, (err, files) => {
                if (err) throw err;
                for (const file of files) {
                    fs.unlink(path.join(tempDir, file), err => {
                        if (err) throw err;
                    });
                }
            });
        });
    });
});

app.listen(3001, () => {
    console.log('Server running on http://localhost:3001');
});

我无法包含完整的错误消息,因为它太长了,但如果有人需要它,我很乐意链接到包含它的文本文件。

我尝试过的:

  1. 验证所有文件路径并确保它们存在。
  2. 转义文件路径以处理文件名中的空格。
  3. 记录构建的FFmpeg命令并手动运行它,仍然产生相同的错误。

环境

  • React.js:v18.3.1
  • Node.js:v22.2.0
  • 快递:v4.19.2
  • FFmpeg:通过 ffmpeg-static 进行静态构建(v5.2.0)
reactjs node.js express audio ffmpeg
1个回答
0
投票

应指定 amix 过滤器的输入,例如对于 4 个输入,

[a0][a1][a2][a3]amix=inputs=4:duration=longest
© www.soinside.com 2019 - 2024. All rights reserved.