Playing streamed custom sound data? #192
-
The title isn't really descriptive, so I'll try to explain as succinctly as possible. I am streaming sound data encoded with Opus from a native app to the discord bot application, and was wondering the correct way to play back this audio stream using songbird and serenity. Currently my approach is to just take the data and make an I was wondering if there is a certain size the buffer sent to Relevant code: pub async fn play_music(sb: std::sync::Arc<Songbird>, mut rcv: mpsc::Receiver<AudioSet>) {
use songbird::input::{
Reader,
Codec,
codec::OpusDecoderState,
Container,
Input,
};
use songbird::tracks::PlayMode;
loop {
// Receive audio data and guild id as a "Set";
let set = match rcv.recv().await {
Some(aset) => aset,
None => continue
};
if let Some(h)= sb.get(set.guild_id) {
let mut handler = h.lock().await;
let audio: Input = Input::new(
true,
Reader::from_memory(set.audio_data),
Codec::Opus(OpusDecoderState::new().unwrap()),
Container::Raw,
None
);
let track_handle = handler.play_source(audio);
//This is simply here to keep the audio from overlapping. Without this, the program plays through
//minutes worth of audio in seconds.
while track_handle.get_info().await.unwrap().playing != PlayMode::End {}
}
}
} Any alternatives for the very temporary and bad while loop at the bottom would also be appreciated 😅. Thanks. EDIT: Forgot to mention, the data that is being played is very small, usually less half a second. Hence why I was asking about the buffer size. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 9 replies
-
A quick update: Changing the buffer size to include audio for more than a second before sending the data over to be played does not work either. Also each packet that is supposed to take slightly more than a second takes wayyyy longer (more than a minute) before the track's status changes to END. This could very easily be a fault in my method here, but that does seem very weird. |
Beta Was this translation helpful? Give feedback.
-
The problem is that 'Raw' and 'Opus' is technically an illegal combination: the frames are not easily self-delimiting. The reason you are getting weird audio popping etc is likely because the Raw container is a) chewing through data at the rate of an uncompressed stream and b) incorrectly decoding since it doesn't know where frame boundaries are. If you want to handle Opus [Ogg-container or WEBM] natively, I'd suggest moving to the next branch. I appreciate this means moving to an in-dev version of serenity which is not nice. The alternative is tagging your frames with lengths as required by DCA and using that. Re: that while loop, please look into the event system. You can register callbacks for track state changes. The source code for TrackQueue is probably educational here. |
Beta Was this translation helpful? Give feedback.
The problem is that 'Raw' and 'Opus' is technically an illegal combination: the frames are not easily self-delimiting.
current
only supports Opus passthrough with the weird DCA format -- our implementation was primarily to un-break the impl that had been shoved into serenity.The reason you are getting weird audio popping etc is likely because the Raw container is a) chewing through data at the rate of an uncompressed stream and b) incorrectly decoding since it doesn't know where frame boundaries are.
If you want to handle Opus [Ogg-container or WEBM] natively, I'd suggest moving to the next branch. I appreciate this means moving to an in-dev version of serenity which is not nice. The alt…