将 ffmpeg 输出直接流式传输到调度程序

Posted

技术标签:

【中文标题】将 ffmpeg 输出直接流式传输到调度程序【英文标题】:Streaming ffmpeg output directly to dispatcher 【发布时间】:2019-11-06 10:36:37 【问题描述】:

我正在尝试使用我的 discord 机器人播放音乐,我想使用 ffmpeg 指定音乐的开头,效果很好,但我只能使用 ffmpeg 下载音乐然后播放。我希望 ffmpeg 对其进行处理,然后将其流式传输以播放音乐。

这是我用来下载然后播放音乐的代码:

message.member.voiceChannel.join().then((con, err) => 
    ytPlay.search_video(op, (id) => 
        let stream = ytdl("https://www.youtube.com/watch?v=" + id, 
            filter: "audioonly"
        );
        let audio = fs.createWriteStream('opStream.divx');

        proc = new ffmpeg(
            source: stream
        )
        proc.withAudioCodec('libmp3lame')
            .toFormat('mp3')
            .seekInput(35)
            .output(audio)
            .run();
        proc.on('end', function() 
            let input = fs.createReadStream('opStream.divx');
            console.log('finished');
            guild.queue.push(id);
            guild.isPlaying = true;
            guild.dispatcher = con.playStream(input);
        );
    );
)

是否可以做我想做的事,如果可以,怎么做?

【问题讨论】:

【参考方案1】:

您可以使用 discord.js 的 seek StreamOptions 来代替使用 ffmpeg 指定音乐的起点,例如:

const dispatcher = connection.play(ytdl(YOUR_URL, filter: 'audioonly' ) , seek:35)

这对我来说效果很好

【讨论】:

【参考方案2】:

是的,这是可能的,我在我的机器人中做到了。 首先你需要安装 ytdl-core

然后创建一个 play.js 文件,流函数将在其中。 此代码将:获取 youtube url 并在不下载歌曲的情况下进行流式传输,将歌曲添加到队列中,让机器人在歌曲完成后离开

根据需要编辑代码。

exports.run = async (client, message, args, ops) => 
    if (!message.member.voiceChannel) return message.channel.send('You are not connected to a voice channel!');


    if (!args[0]) return message.channel.send('Insert a URL!');
    let validate = await ytdl.validateURL(args[0]);

    let info = await  ytdl.getInfo(args[0]);

   let data = ops.active.get(message.guild.id) || ;
    if (!data.connection) data.connection = await message.member.voiceChannel.join();
    if(!data.queue) data.queue = [];
    data.guildID = message.guild.id;

    data.queue.push(
        songTitle: info.title,
        requester: message.author.tag,
        url: args[0],
        announceChannel: message.channel.id

    );

    if (!data.dispatcher) play(client, ops, data);
    else 
        message.channel.send(`Added to queue: $info.title | requested by: $message.author.tag`)
    
    ops.active.set(message.guild.id, data);



async function play(client, ops, data) 
    client.channels.get(data.queue[0].announceChannel).send(`Now Playing: $data.queue[0].songTitle | Requested by: $data.queue[0].requester`);
    client.user.setActivity(`$data.queue[0].songTitle`, type: "LISTENING");

    data.dispatcher = await data.connection.playStream(ytdl(data.queue[0].url, filter: 'audioonly'));
    data.dispatcher.guildID = data.guildID;

    data.dispatcher.once('end', function() 
        end(client, ops, this);

    );


function end(client, ops, dispatcher)

    let fetched = ops.active.get(dispatcher.guildID);

    fetched.queue.shift();

    if (fetched.queue.length > 0) 
        ops.active.set(dispatcher.guildID, fetched);
        play(client, ops, fetched);
     else 
        ops.active.delete(dispatcher.guildID);

        let vc = client.guilds.get(dispatcher.guildID).me.voiceChannel;

        if (vc) vc.leave();


    
  
  module.exports.help = 
    name:"play"
  ``` 

【讨论】:

这不是我想要的。我想流式传输 ffmpeg 输出。如果您准确地阅读了我的代码,您会注意到我已经使用了 ytdl。 @心理

以上是关于将 ffmpeg 输出直接流式传输到调度程序的主要内容,如果未能解决你的问题,请参考以下文章

我可以将多个 ffmpeg 输出通过管道传输到不同的管道吗?

使用FFMPEG将视频文件连续传输到RTMP服务器

libav / FFMPEG以一种编码方式进行流式传输,另存为另一种方式

将控制台应用程序的标准输出流式传输到 ASP.NET MVC 视图

使用 FFmpeg 从 Mac 流式传输网络摄像头

如何将视频从我的应用程序流式传输到网络?