将 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 输出通过管道传输到不同的管道吗?
libav / FFMPEG以一种编码方式进行流式传输,另存为另一种方式