Saving an opus stream from a voice channel to .mp3/.wav/.webm
So with the help of another thread here, I managed to save an opus stream to .ogg. Now, I need to save that same opus stream to an .mp3 file instead, and i’m even more stuck than last time.
Can I somehow save the audio to a .mp3 or .wav file instead?
Help would be much mich appreciated…
37 Replies
- What's your exact discord.js
npm list discord.js
and node node -v
version?
- Not a discord.js issue? Check out #other-js-ts.
- Consider reading #how-to-get-help to improve your question!
- Explain what exactly your issue is.
- Post the full error stack trace, not just the top part!
- Show your code!
- Issue solved? Press the button!
- ✅
Marked as resolved by OPYou must use ffmpeg for that
You can use prism-media's ffmpeg class, which is basically a cp.spawn
Then, pipe to ffmpeg, and write the output to a file
Also, if you're not going to pipe with createWriteStream, use fs.writeFile
To be honest, I don't feel to sure in this field at all.
Is that the way I'm supposed to do it? I keep getting EOF.
You shouldn't need to manually end audioOutput
Please also provide backtrace of the error
Oh, sorry, completely fogot.
So basically, this works perfectly: (without converting the file to mp3, of course)
However, the moment I uncomment
opusStream.pipe(audioOutput);
, "end" never gets emitted on opusStream
So I tried rewiring both events to audioOutput:
But now the stream's "end" gets emitted almost immediately (40ms, independent of when opusStream (the user talking) actualkly ends)...
I suspect the args for FFmpeg are wrong to some extent, but I lack the experience with the module to actually tell whereTry removing -i pipe:0, it should be added by prism-media by default
That actually works! The last problem is that the written file is unreadable, yet again.
If you want to save to a file
Use -i filename, don't use fs
That way you have faster execution and allows you to not need to save all data to an array
If you simply want to send to Discord, you don't need to save to a file though
No, I have to send the file to a different API that only accepts files
Well I tried, but the moment I add that "-i" flag, it goes back to the 40ms problem
Unless it's a library, it will always accept buffers
-i file.mp3?
Yeah
args: ["-f", "opus", "-ar", "48000", "-ac", "2", "-codec:a", "libmp3lame", "-i", "output.mp3"]
oops 🤦♂️ Messed up with the arguments
remove the -i
Oh I wondered, it means input, right?
Yep, I confused it with output
Okay, the file is still not playable, and now it seems to trigger on("end") over and over again
Because instead of a single "started speaking/stopped speaking" log it's just spam
Save the opus to a file, and try using ffmpeg via command-line to see what happens
Well "end" triggers correctly - but only if that .on("data) event is there
Not sure if the file has anything usable inside, but one gets written and it takes 8KB; The ones written by ffmpeg are all 0KB
I don't remember ever being this confused before -_-
Actually no, ffmpeg doesn't write a file at all
I tried saving it into a buffer and putting that into a fs write stream, and the written file is still 0KB. I think the ffmpeg command ight still be wrong
OOps
Okay nevermind, it totally works
Discord buggy
With cmd or with the code?
I downloaded a different file and it converted it with those arguments.
With cmd
Oh not anymore
Hang on I've got an idea
Also, you forgot to .end the opusStream
wait nvm
Doesn't it end automatically through discordjs?
Yeah
Yep, I was confusing with fs write stream
Ensure you're properly saving
Okay well, cmd doesn't work if you specify the format to opus
However, the part in js still doesn't save the file at all
Right now it looks like this...
Thanks for your time, by the way
What outputs if you
ffprobe inputfile
?
Np alsoI don't have an actual input file since it all comes from the opus stream, but trying it with the placeholder one I get
Save it to a file, and execute ffprobe
Like this, right?
Invalid data...
I'm not sure if I'm saving it correctly though; When we saved it as .ogg, it used to work
I'm curious
If you add ogg head to it, and try to ffprobe it, what happens?
FFmpeg probably doesn't support opus like that
Well I still have an ogg file saved from yesterday
Nothing in that respect should've changed, so
Input #0, ogg, from 'output.ogg':
Duration: 00:00:02.56, start: 0.000000, bitrate: 59 kb/s
Stream #0:0: Audio: opus, 48000 Hz, stereo, fltp
Yeah it works properly
Maybe we have to use some other library after all. I didn't come far with it previously, but maybe discordjs/opus?
It has some kind of opus encoder/decoder, but I couldn't find any documentationJust add ogg heads and pass to ffmpeg
Done
But for that I would need the prism-media alpha version again
Wouldn't it break the FFmpeg class?
Yeah I have no idea anymore.. Guess I'll try to continue tomorrow, but I'm pretty sure I'm doing that part wrong
Not really, you'll just need to pipe 2x
Okay I tried real quick, and the problem with end triggering over and over is there again.
I'll see what I can do in way of debugging tomorrow, but
Okay so being me
I couldn't just let the problem hang and focus on my other work
So in the end, I just decided to run the ffmeg command through the terminal instead of using that prism-media class to convert the written .ogg file to .mp3.
Once again, thanks a ton for your help - it's probably what you meant earlier, too. Definitely couldn't have done it alone..
(Also, prism-media also executes through shell, soo..)
(Funny, couldn't get it to work that way)