You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于instagram-private-api的Bot发布Instagram视频故事报错问询

问题排查与修复方案

报错根本原因

  • 代码未区分图片/视频资源,所有读取到的文件都会传入sharp库执行JPEG格式转换,视频二进制流传入sharp会直接抛出异常,你看到的error: undefined是错误栈未被完整打印导致的
  • instagram-private-api的故事发布接口对图片、视频的传参要求不同,当前代码只适配了图片发布的参数逻辑
  • 未做视频合规性校验,Instagram故事视频要求时长≤15秒、分辨率为9:16、编码为H.264、音频编码为AAC,不符合规范的视频也会触发发布失败

适配方案

第一步:新增依赖(可选,用于视频自动转码适配规范)

如果需要自动处理不符合规范的视频,先安装依赖:

npm install fluent-ffmpeg
# 同时确保你的设备已安装ffmpeg环境,Windows可通过scoop install ffmpeg安装,Mac可通过brew install ffmpeg安装

第二步:修改核心发布逻辑

替换你代码中post函数里读取文件后的处理逻辑即可:

// 首先在文件顶部引入依赖
const ffmpeg = require('fluent-ffmpeg');
const { extname } = require('path');

// 以下是修改后的post函数
async function post() {
    logger.info("Post() called! ======================");
    
    let postPromise = fsp.readdir(imgFolderPath)
    .then(filenames => {
        if (filenames.length < 1) throw new Error(`Folder ${imgFolderPath} is empty...`)
        logger.debug(`${filenames.length} files found in ${imgFolderPath}`);
        return filenames;
    })
    .then(filenames => filenames.map(file => path.resolve(imgFolderPath + file)))
    .then(filenames => pickUnusedFileFrom(filenames, filenames.length))
    .then(filename => {
        if (!dryrun) registerFileUsed(filename)
        // 把文件名和后缀一起传下去,方便后续判断类型
        return {
            path: filename,
            ext: extname(filename).toLowerCase()
        }
    })
    .then(async ({path, ext}) => {
        const buffer = await fsp.readFile(path);
        logger.debug("Read File Success ");
        let publishParams;
        // 图片处理逻辑
        if (['.jpg', '.jpeg', '.png', '.webp'].includes(ext)) {
            const processedImg = await sharp(buffer).jpeg().toBuffer();
            logger.debug("Sharp JPEG Success");
            publishParams = { file: processedImg };
        } 
        // 视频处理逻辑
        else if (['.mp4', '.mov'].includes(ext)) {
            // 如果不需要转码,直接传buffer即可
            publishParams = { video: buffer };
            // 如果需要自动转码适配Instagram规范,用下面这段替代上面的行
            /*
            const tempPath = path.resolve(imgFolderPath, `temp_${Date.now()}.mp4`);
            await new Promise((resolve, reject) => {
                ffmpeg(path)
                    .size('1080x1920') // 9:16分辨率
                    .duration(15) // 截断到15秒
                    .videoCodec('libx264')
                    .audioCodec('aac')
                    .output(tempPath)
                    .on('end', resolve)
                    .on('error', reject)
                    .run();
            });
            const videoBuffer = await fsp.readFile(tempPath);
            await fsp.unlink(tempPath); // 删除临时文件
            publishParams = { video: videoBuffer };
            */
            logger.debug("Video processing completed");
        } else {
            throw new Error(`Unsupported file type: ${ext}`);
        }
        return publishParams;
    })
    .then(async publishParams => {
        if (!dryrun) {
            return ig.publish.story(publishParams)
            .then(fb => logger.info("Posting successful!"))
        } 
        else return logger.info("Data not sent, dryrun = true")
    })
    .then(() => logger.info(`Next post scheduled for ${job.nextDates()}\n`))
    // 修改错误打印逻辑,输出完整错误栈方便排查
    .catch(err => {
        logger.error(err);
        logger.error(err.stack || 'No error stack available');
    })
}

其他优化建议

  • 可以把imgFolderPath变量名改成更通用的resourceFolderPath,避免歧义
  • 若不需要自动转码,确保你上传的视频本身符合Instagram故事的格式要求,避免发布失败

内容的提问来源于stack exchange,提问作者Shrimanta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 23:57:05