@@ -355,8 +355,9 @@ class FFmpegOpusAudio(FFmpegAudio):
355
355
The codec to use to encode the audio data. Normally this would be
356
356
just ``libopus``, but is used by :meth:`FFmpegOpusAudio.from_probe` to
357
357
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``.
360
361
361
362
.. warning::
362
363
@@ -407,7 +408,9 @@ def __init__(
407
408
args .append ("-i" )
408
409
args .append ("-" if pipe else source )
409
410
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"
411
414
412
415
args .extend (
413
416
(
@@ -417,17 +420,24 @@ def __init__(
417
420
"opus" ,
418
421
"-c:a" ,
419
422
codec ,
420
- "-ar" ,
421
- "48000" ,
422
- "-ac" ,
423
- "2" ,
424
- "-b:a" ,
425
- f"{ bitrate } k" ,
426
423
"-loglevel" ,
427
424
"warning" ,
428
425
)
429
426
)
430
427
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
+
431
441
if isinstance (options , str ):
432
442
args .extend (shlex .split (options ))
433
443
@@ -501,6 +511,8 @@ def custom_probe(source, executable):
501
511
502
512
executable = kwargs .get ("executable" )
503
513
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"
504
516
return cls (source , bitrate = bitrate , codec = codec , ** kwargs ) # type: ignore
505
517
506
518
@classmethod
@@ -717,6 +729,9 @@ def __init__(self, source: AudioSource, client: VoiceClient, *, after=None):
717
729
raise TypeError ('Expected a callable for the "after" parameter.' )
718
730
719
731
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 ()
720
735
self .loops = 0
721
736
self ._start = time .perf_counter ()
722
737
@@ -740,7 +755,13 @@ def _do_run(self) -> None:
740
755
self ._start = time .perf_counter ()
741
756
742
757
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 ()
744
765
745
766
if not data :
746
767
self .stop ()
0 commit comments