【翻訳】Pixel Streaming ― オーディオのクオリティが低い

(このスレッドは、Pixel Streaming - Audio has bad qualityを翻訳したものです。)

Pixel Streaming によるビルドを動かすことができるようになり、この結果には非常に満足しているのですが、Pixel Streaming を使って質のよいオーディオ信号を得ることができないという大きな問題に直面しています。そのクオリティはとても低く、モノラルでしか再生されません。どの部分を調べて、もっとよい設定を行うことができるのか分からないでいます。このような問題を経験された方はいませんか?どこを調べたらよいかヒントをいただけませんでしょうか?ソースコードをざっと見てみましたが、このための設定を調整するファイルが見つけることができませんでした。何か助言をいただけますと、大変助かります!

本件問題の所在が見つけられたようです。そのための修正は、エンジンの今後のバージョンに含まれることになりますが、今修正を行いたい場合は、2 つのファイルを変更してください。

まず、Engine\Plugins\Media\PixelStreaming\Source\PixelStreaming\Private\Streamer.cpp において、FStreamer::AddStreams() が cricket::AudioOptions 構造体を使用するようにします。この関数の修正後の全体は次のようになります。

void FStreamer::AddStreams(FPlayerId PlayerId)
 {
     const FString StreamId = TEXT("stream_id");
     const char AudioLabel[] = "audio_label";
     const char VideoLabel[] = "video_label";
 
     FPlayerSession* Session = GetPlayerSession(PlayerId);
     check(Session);
     
     cricket::AudioOptions AudioSourceOptions;
     AudioSourceOptions.echo_cancellation = false;
     AudioSourceOptions.auto_gain_control = false;
     AudioSourceOptions.noise_suppression = false;
 
     if (bPlanB)
     {
         rtc::scoped_refptr<webrtc::MediaStreamInterface> Stream;
 
         if (auto* StreamPtr = Streams.Find(StreamId))
         {
             Stream = *StreamPtr;
         }
         else
         {
             Stream = PeerConnectionFactory->CreateLocalMediaStream(TCHAR_TO_ANSI(*StreamId));
 
             rtc::scoped_refptr<webrtc::AudioTrackInterface> AudioTrackLocal(
                 PeerConnectionFactory->CreateAudioTrack(AudioLabel, PeerConnectionFactory->CreateAudioSource(AudioSourceOptions)));
 
             Stream->AddTrack(AudioTrackLocal);
 
             auto VideoCapturerStrong = std::make_unique<FVideoCapturer>(HWEncoderDetails);
             VideoCapturer = VideoCapturerStrong.get();
             rtc::scoped_refptr<webrtc::VideoTrackInterface> VideoTrackLocal(PeerConnectionFactory->CreateVideoTrack(
                 VideoLabel, PeerConnectionFactory->CreateVideoSource(std::move(VideoCapturerStrong))));
 
             Stream->AddTrack(VideoTrackLocal);
 
             Streams[StreamId] = Stream;
         }
 
         verifyf(Session->GetPeerConnection().AddStream(Stream), TEXT("Failed to add stream for player %u"), PlayerId);
     }
     else
     {
         if (!Session->GetPeerConnection().GetSenders().empty())
         {
             return;  // Already added tracks
         }
 
         if (!AudioTrack)
         {
             AudioTrack =
                 PeerConnectionFactory->CreateAudioTrack(AudioLabel, PeerConnectionFactory->CreateAudioSource(AudioSourceOptions));
         }
 
         if (!VideoTrack)
         {
             auto VideoCapturerStrong = std::make_unique<FVideoCapturer>(HWEncoderDetails);
             VideoCapturer = VideoCapturerStrong.get();
             VideoTrack = PeerConnectionFactory->CreateVideoTrack(
                 VideoLabel, PeerConnectionFactory->CreateVideoSource(std::move(VideoCapturerStrong)));
         }
 
         auto Res = Session->GetPeerConnection().AddTrack(AudioTrack, { TCHAR_TO_ANSI(*StreamId) });
         if (!Res.ok())
         {
             UE_LOG(PixelStreamer, Error, TEXT("Failed to add AudioTrack to PeerConnection of player %u. Msg=%s"), Session->GetPlayerId(), ANSI_TO_TCHAR(Res.error().message()));
         }
 
         Res = Session->GetPeerConnection().AddTrack(VideoTrack, { TCHAR_TO_ANSI(*StreamId) });
         if (!Res.ok())
         {
             UE_LOG(PixelStreamer, Error, TEXT("Failed to add VideoTrack to PeerConnection of player %u. Msg=%s"), Session->GetPlayerId(), ANSI_TO_TCHAR(Res.error().message()));
         }
     }
 }

さらに、Engine/Source/Programs/PixelStreaming/WebServers/SignallingWebServer/scripts/webRtcPlayer.js において、handleCreateOffer を次のように変更してください。

         handleCreateOffer = function (pc) {
             pc.createOffer(self.sdpConstraints).then(function (offer) {
                 offer.sdp = offer.sdp.replace("useinbandfec=1", "useinbandfec=1;stereo=1;maxaveragebitrate=128000");
                 pc.setLocalDescription(offer);
                 if (self.onWebRtcOffer) {
                     // (andriy): increase start bitrate from 300 kbps to 20 mbps and max bitrate from 2.5 mbps to 100 mbps
                     // (100 mbps means we don't restrict encoder at all)
                     // after we `setLocalDescription` because other browsers are not c happy to see google-specific config
                     offer.sdp = offer.sdp.replace(/(a=fmtp:\d+ .*level-asymmetry-allowed=.*)\r\n/gm, "$1;x-google-start-bitrate=10000;x-google-max-bitrate=20000\r\n");
                     self.onWebRtcOffer(offer);
                 }
             },
             function () { console.warn("Couldn't create offer") });
         }