@@ -355,8 +355,9 @@ class FFmpegOpusAudio(FFmpegAudio):
355355 The codec to use to encode the audio data. Normally this would be
356356 just ``libopus``, but is used by :meth:`FFmpegOpusAudio.from_probe` to
357357 opportunistically skip pointlessly re-encoding Opus audio data by passing
358- ``copy`` as the codec value. Any values other than ``copy``, ``opus``, or
359- ``libopus`` will be considered ``libopus``. Defaults to ``libopus``.
358+ ``copy`` as the codec value. Any values other than ``copy``, or
359+ ``libopus`` will be considered ``libopus``. ``opus`` will also be considered
360+ ``libopus`` since the ``opus`` encoder is still in development. Defaults to ``libopus``.
360361
361362 .. warning::
362363
@@ -407,7 +408,9 @@ def __init__(
407408 args .append ("-i" )
408409 args .append ("-" if pipe else source )
409410
410- codec = "copy" if codec in ("opus" , "libopus" ) else "libopus"
411+ # use "libopus" when "opus" is specified since the "opus" encoder is incomplete
412+ # link to ffmpeg docs: https://www.ffmpeg.org/ffmpeg-codecs.html#opus
413+ codec = "copy" if codec == "copy" else "libopus"
411414
412415 args .extend (
413416 (
@@ -417,17 +420,24 @@ def __init__(
417420 "opus" ,
418421 "-c:a" ,
419422 codec ,
420- "-ar" ,
421- "48000" ,
422- "-ac" ,
423- "2" ,
424- "-b:a" ,
425- f"{ bitrate } k" ,
426423 "-loglevel" ,
427424 "warning" ,
428425 )
429426 )
430427
428+ # only pass in bitrate, sample rate, channels arguments when actually encoding to avoid ffmpeg warnings
429+ if codec != "copy" :
430+ args .extend (
431+ (
432+ "-ar" ,
433+ "48000" ,
434+ "-ac" ,
435+ "2" ,
436+ "-b:a" ,
437+ f"{ bitrate } k" ,
438+ )
439+ )
440+
431441 if isinstance (options , str ):
432442 args .extend (shlex .split (options ))
433443
@@ -501,6 +511,8 @@ def custom_probe(source, executable):
501511
502512 executable = kwargs .get ("executable" )
503513 codec , bitrate = await cls .probe (source , method = method , executable = executable )
514+ # only re-encode if the source isn't already opus, else directly copy the source audio stream
515+ codec = "copy" if codec in ("opus" , "libopus" ) else "libopus"
504516 return cls (source , bitrate = bitrate , codec = codec , ** kwargs ) # type: ignore
505517
506518 @classmethod
@@ -717,6 +729,9 @@ def __init__(self, source: AudioSource, client: VoiceClient, *, after=None):
717729 raise TypeError ('Expected a callable for the "after" parameter.' )
718730
719731 def _do_run (self ) -> None :
732+ # attempt to read first audio segment from source before starting
733+ # some sources can take a few seconds and may cause problems
734+ first_data = self .source .read ()
720735 self .loops = 0
721736 self ._start = time .perf_counter ()
722737
@@ -740,7 +755,13 @@ def _do_run(self) -> None:
740755 self ._start = time .perf_counter ()
741756
742757 self .loops += 1
743- data = self .source .read ()
758+ # Send the data read from the start of the function if it is not None
759+ if first_data is not None :
760+ data = first_data
761+ first_data = None
762+ # Else read the next bit from the source
763+ else :
764+ data = self .source .read ()
744765
745766 if not data :
746767 self .stop ()
0 commit comments