#ifndef SYS_AUDIO_SOURCE_HXX
#define SYS_AUDIO_SOURCE_HXX
#include
#include "rtc_audio_source.h"
#include "rtc_peerconnection_factory.h"
#include
#include
#include
#if defined(_WIN32) || defined(WINDOWS)
#include "win_sys_audio_capturer.h"
#elif defined(linux) || defined(LINUX)
#include "linux_sys_audio_capturer.h"
#else
#pragma message("SysAudioSource is only available on Windows and Linux (stub)")
#endif
namespace flutter_webrtc_plugin {
using namespace libwebrtc;
#if defined(_WIN32) || defined(WINDOWS)
using PlatformSysAudioCapturer = WinSysAudioCapturer;
#elif defined(linux) || defined(LINUX)
using PlatformSysAudioCapturer = LinuxSysAudioCapturer;
#endif
class SysAudioSource : public RTCAudioSource {
public:
SysAudioSource(scoped_refptr factory,
const std::string& audio_source_label = "sys_audio_input");
~SysAudioSource() override;
bool Initialize(const std::string& device_id = "");
bool StartCapture();
void StopCapture();
bool IsCapturing() const;
void CaptureFrame(const void* audio_data, int bits_per_sample,
int sample_rate, size_t number_of_channels,
size_t number_of_frames) override {
if (enable_pcm_recording_ && pcm_file_.is_open()) {
pcm_file_.write(static_cast<const char*>(audio_data),
bits_per_sample / 8 * number_of_channels * number_of_frames);
pcm_file_.flush();
total_frames_recorded_ += number_of_frames;
}
// std::cout << "sink size:" << rtc_audio_source_->GetSinkSize() << std::endl;
// std::cout << bits_per_sample << " " << sample_rate << " " << number_of_channels << " " << number_of_frames << std::endl;
rtc_audio_source_->CaptureFrame(audio_data, bits_per_sample, sample_rate,
number_of_channels, number_of_frames);
} else {
std::cout << "rtc_audio_source_ is null" << std::endl;
}
}
SourceType GetSourceType() const override {
return SourceType::kCustom;
}
scoped_refptr rtc_audio_source() {
return rtc_audio_source_;
}
int GetSinkSize() override {
return rtc_audio_source_->GetSinkSize();
}
void EnablePcmRecording(bool enable, const std::string& file_path) {
if (enable) {
pcm_file_.open(file_path, std::ios::binary);
if (pcm_file_.is_open()) {
enable_pcm_recording_ = true;
total_frames_recorded_ = 0;
std::cout << "PCM recording started: " << file_path << std::endl;
} else {
std::cout << "Failed to open PCM file: " << file_path << std::endl;
}
} else {
enable_pcm_recording_ = false;
if (pcm_file_.is_open()) {
pcm_file_.close();
std::cout << "PCM recording stopped. Total frames: "
<< total_frames_recorded_ << std::endl;
}
}
}
bool IsPcmRecordingEnabled() const {
return enable_pcm_recording_;
}
private:
static void OnAudioDataCallback(const void* audio_data,
int bits_per_sample,
int sample_rate,
size_t number_of_channels,
size_t number_of_frames,
void* user_data);
std::unique_ptr capturer_;
scoped_refptr factory_;
scoped_refptr rtc_audio_source_;
std::string audio_source_label_;
bool enable_pcm_recording_ = false;
std::ofstream pcm_file_;
size_t total_frames_recorded_ = 0;
};
} // namespace flutter_webrtc_plugin
#endif // SYS_AUDIO_SOURCE_HXX
#include "sys_audio_source.h"
#include
namespace flutter_webrtc_plugin {
SysAudioSource::SysAudioSource(
scoped_refptr factory,
const std::string& audio_source_label)
: factory_(factory), audio_source_label_(audio_source_label) {
std::cout << "Creating SysAudioSource: " << audio_source_label;
RTCAudioOptions options;
options.echo_cancellation = false;
options.noise_suppression = false;
options.auto_gain_control = false;
options.highpass_filter = false;
rtc_audio_source_ = factory_->CreateAudioSource(
audio_source_label.c_str(),
RTCAudioSource::SourceType::kCustom,
options);
if (rtc_audio_source_) {
capturer_ = std::make_unique();
capturer_->SetCallback(&SysAudioSource::OnAudioDataCallback, this);
std::cout << "SysAudioSource created successfully";
} else {
std::cout << "Failed to create RTCAudioSource";
}
}
SysAudioSource::~SysAudioSource() {
std::cout << "Destroying SysAudioSource";
StopCapture();
rtc_audio_source_ = nullptr;
}
bool SysAudioSource::Initialize(const std::string& device_id) {
if (!capturer_) {
std::cout << "Capturer not initialized";
return false;
}
bool result = capturer_->Initialize(device_id);
if (result) {
std::cout << "SysAudioSource initialized with device: "
<< (device_id.empty() ? "default" : device_id);
} else {
std::cout << "Failed to initialize SysAudioSource (platform may not support it)";
}
return result;
}
bool SysAudioSource::StartCapture() {
if (!capturer_) {
std::cout << "Cannot start capture - capturer is null";
return false;
}
if (capturer_->IsCapturing()) {
std::cout << "Already capturing";
return true;
}
bool result = capturer_->StartCapture();
if (result) {
std::cout << "Started sys audio capture";
} else {
std::cout << "Failed to start sys audio capture (platform may not support it)";
}
return result;
}
void SysAudioSource::StopCapture() {
if (capturer_ && capturer_->IsCapturing()) {
capturer_->StopCapture();
std::cout << "Stopped sys audio capture";
}
}
bool SysAudioSource::IsCapturing() const {
return capturer_ ? capturer_->IsCapturing() : false;
}
void SysAudioSource::OnAudioDataCallback(const void* audio_data,
int bits_per_sample,
int sample_rate,
size_t number_of_channels,
size_t number_of_frames,
void* user_data) {
SysAudioSource* self = static_cast<SysAudioSource*>(user_data);
if (self) {
self->CaptureFrame(audio_data, bits_per_sample, sample_rate,
number_of_channels, number_of_frames);
}
}
} // namespace flutter_webrtc_plugin
sink可以触发,向里面发送数据但是远程的peerconection无法接收到。
flutter: report => {
flutter: id: T01,
flutter: type: transport,
flutter: timestamp: 1774874753187447.0,
flutter: values => {
flutter: bytesReceived : 721,
flutter: bytesSent : 698,
flutter: dtlsCipher : TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
flutter: dtlsRole : client,
flutter: dtlsState : connected,
flutter: iceLocalUsernameFragment : Aq26,
flutter: iceRole : controlled,
flutter: iceState : connected,
flutter: localCertificateId : CF3C:1A:91:3D:2C:C7:4E:71:B6:79:72:75:B9:E6:CD:FC:33:A9:03:4F:70:BA:33:6B:41:9B:15:F3:4C:09:1E:5D,
flutter: packetsReceived : 2,
flutter: packetsSent : 2,
flutter: remoteCertificateId : CF8D:2D:B5:B8:AD:27:B2:F7:8D:E2:10:DA:04:FE:B6:4B:01:13:26:BC:DC:35:9E:68:2F:A4:24:C1:87:74:55:99,
flutter: selectedCandidatePairChanges : 1,
flutter: selectedCandidatePairId : CPKxHVStaL_cIePVcEY,
flutter: srtpCipher : AES_CM_128_HMAC_SHA1_80,
flutter: tlsVersion : FEFD,
flutter: }
flutter: }
flutter: report => {
flutter: id: CF3C:1A:91:3D:2C:C7:4E:71:B6:79:72:75:B9:E6:CD:FC:33:A9:03:4F:70:BA:33:6B:41:9B:15:F3:4C:09:1E:5D,
flutter: type: certificate,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: base64Certificate : MIIBFTCBvaADAgECAgkAxLzdGpK1SoQwCgYIKoZIzj0EAwIwETEPMA0GA1UEAwwGV2ViUlRDMB4XDTI2MDMyOTEyNDUwNFoXDTI2MDQyOTEyNDUwNFowETEPMA0GA1UEAwwGV2ViUlRDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESl+GWmPHfWGcotiy2c1NvxvPM9ahDIOXkzyW4nwx06c+BW3vJv1xVKu5488BdQVQVkld+tHugkBf7gL3A0zCyDAKBggqhkjOPQQDAgNHADBEAiB8viLhWqrVzQk983MOMc1yuTZ4GaRUVwLIJ7TgKpgyCwIgScdrM6/zKrvGwlwMJ3rp4QZHJBS9+nbW2gv/vVIMRx8=,
flutter: fingerprint : 3C:1A:91:3D:2C:C7:4E:71:B6:79:72:75:B9:E6:CD:FC:33:A9:03:4F:70:BA:33:6B:41:9B:15:F3:4C:09:1E:5D,
flutter: fingerprintAlgorithm : sha-256,
flutter: }
flutter: }
flutter: report => {
flutter: id: CF8D:2D:B5:B8:AD:27:B2:F7:8D:E2:10:DA:04:FE:B6:4B:01:13:26:BC:DC:35:9E:68:2F:A4:24:C1:87:74:55:99,
flutter: type: certificate,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: base64Certificate : MIIBFjCBvKADAgECAggDOiiGHpaqXjAKBggqhkjOPQQDAjARMQ8wDQYDVQQDDAZXZWJSVEMwHhcNMjYwMzI5MTI0NTA0WhcNMjYwNDI5MTI0NTA0WjARMQ8wDQYDVQQDDAZXZWJSVEMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATxCKelMmxcjXOjbLbfvyKR2kzJz1uO/5yOdho8sUcgCsWdC3zJYgupb8CqsHUqhFY5EI15SYw5PxFd7ssSKuY8MAoGCCqGSM49BAMCA0kAMEYCIQD4gf2AfJBo0l+pdNTLDdZZ+/QxXWpkAkQWncothgcLiwIhAM7p4AbvM6agIHau45c3ve+o5o5EN8vMXPFDq6RS6Xqo,
flutter: fingerprint : 8D:2D:B5:B8:AD:27:B2:F7:8D:E2:10:DA:04:FE:B6:4B:01:13:26:BC:DC:35:9E:68:2F:A4:24:C1:87:74:55:99,
flutter: fingerprintAlgorithm : sha-256,
flutter: }
flutter: }
flutter: report => {
flutter: id: CPKxHVStaL_cIePVcEY,
flutter: type: candidate-pair,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: availableOutgoingBitrate : 2000000.0,
flutter: bytesDiscardedOnSend : 0,
flutter: bytesReceived : 721,
flutter: bytesSent : 698,
flutter: consentRequestsSent : 21,
flutter: currentRoundTripTime : 0.0,
flutter: lastPacketReceivedTimestamp : 1774874707186.0,
flutter: lastPacketSentTimestamp : 1774874707182.0,
flutter: localCandidateId : IKxHVStaL,
flutter: nominated : true,
flutter: packetsDiscardedOnSend : 0,
flutter: packetsReceived : 2,
flutter: packetsSent : 2,
flutter: priority : 9114756780654345726,
flutter: remoteCandidateId : IcIePVcEY,
flutter: requestsReceived : 22,
flutter: requestsSent : 22,
flutter: responsesReceived : 22,
flutter: responsesSent : 22,
flutter: state : succeeded,
flutter: totalRoundTripTime : 0.004,
flutter: transportId : T01,
flutter: writable : true,
flutter: }
flutter: }
flutter: report => {
flutter: id: IKxHVStaL,
flutter: type: local-candidate,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: address : 10.1.2.211,
flutter: candidateType : host,
flutter: foundation : 3460999637,
flutter: ip : 10.1.2.211,
flutter: isRemote : false,
flutter: networkAdapterType : wifi,
flutter: networkType : wifi,
flutter: port : 64627,
flutter: priority : 2122194687,
flutter: protocol : udp,
flutter: transportId : T01,
flutter: usernameFragment : Aq26,
flutter: vpn : false,
flutter: }
flutter: }
flutter: report => {
flutter: id: IT01A296816917,
flutter: type: inbound-rtp,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: audioLevel : 0.0,
flutter: bytesReceived : 0,
flutter: concealedSamples : 0,
flutter: concealmentEvents : 0,
flutter: delayedPacketOutageSamples : 0,
flutter: fecPacketsDiscarded : 0,
flutter: fecPacketsReceived : 0,
flutter: headerBytesReceived : 0,
flutter: insertedSamplesForDeceleration : 0,
flutter: interruptionCount : 0,
flutter: jitter : 0.0,
flutter: jitterBufferDelay : 0.0,
flutter: jitterBufferEmittedCount : 0,
flutter: jitterBufferFlushes : 0,
flutter: jitterBufferMinimumDelay : 0.0,
flutter: jitterBufferTargetDelay : 0.0,
flutter: kind : audio,
flutter: mid : 0,
flutter: packetsDiscarded : 0,
flutter: packetsLost : 0,
flutter: packetsReceived : 0,
flutter: relativePacketArrivalDelay : 0.0,
flutter: removedSamplesForAcceleration : 0,
flutter: silentConcealedSamples : 0,
flutter: ssrc : 296816917,
flutter: totalAudioEnergy : 0.0,
flutter: totalInterruptionDuration : 0.0,
flutter: totalProcessingDelay : 0.0,
flutter: totalSamplesDuration : 47.019999999999214,
flutter: totalSamplesReceived : 0,
flutter: trackIdentifier : 6dada39b-21bc-4597-9fd4-4e88382ac1a4,
flutter: transportId : T01,
flutter: }
flutter: }
flutter: report => {
flutter: id: IcIePVcEY,
flutter: type: remote-candidate,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: address : 10.1.2.211,
flutter: candidateType : host,
flutter: foundation : 1706040316,
flutter: ip : 10.1.2.211,
flutter: isRemote : true,
flutter: port : 65133,
flutter: priority : 2122194687,
flutter: protocol : udp,
flutter: transportId : T01,
flutter: usernameFragment : DiET,
flutter: }
flutter: }
flutter: report => {
flutter: id: T01,
flutter: type: transport,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: bytesReceived : 721,
flutter: bytesSent : 698,
flutter: dtlsCipher : TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
flutter: dtlsRole : client,
flutter: dtlsState : connected,
flutter: iceLocalUsernameFragment : Aq26,
flutter: iceRole : controlled,
flutter: iceState : connected,
flutter: localCertificateId : CF3C:1A:91:3D:2C:C7:4E:71:B6:79:72:75:B9:E6:CD:FC:33:A9:03:4F:70:BA:33:6B:41:9B:15:F3:4C:09:1E:5D,
flutter: packetsReceived : 2,
flutter: packetsSent : 2,
flutter: remoteCertificateId : CF8D:2D:B5:B8:AD:27:B2:F7:8D:E2:10:DA:04:FE:B6:4B:01:13:26:BC:DC:35:9E:68:2F:A4:24:C1:87:74:55:99,
flutter: selectedCandidatePairChanges : 1,
flutter: selectedCandidatePairId : CPKxHVStaL_cIePVcEY,
flutter: srtpCipher : AES_CM_128_HMAC_SHA1_80,
flutter: tlsVersion : FEFD,
flutter: }
flutter: }
flutter: Have a Sender of kind:audio
flutter: Setting direction and replacing track with null
flutter: LocalRenegotiationNeeded
LocalAudioSource RemoveSink1
MediaStreamForId: b4edfbb4-cce1-4d9f-aa60-8dc0958ab556
flutter: local pc: onSignalingState(RTCSignalingState.RTCSignalingStateHaveLocalOffer), state2(RTCSignalingState.RTCSignalingStateHaveLocalOffer)
flutter: remote pc: onSignalingState(RTCSignalingState.RTCSignalingStateHaveRemoteOffer), state2(RTCSignalingState.RTCSignalingStateHaveRemoteOffer)
flutter: remote pc: onSignalingState(RTCSignalingState.RTCSignalingStateStable), state2(RTCSignalingState.RTCSignalingStateStable)
MediaStreamForId: b4edfbb4-cce1-4d9f-aa60-8dc0958ab556
bytesReceived 的值没有什么变化,表示远端没有接收到数据(我可以保证是一直发送数据的 ondata方法一直被调用)
#ifndef SYS_AUDIO_SOURCE_HXX
#define SYS_AUDIO_SOURCE_HXX
#include
#include "rtc_audio_source.h"
#include "rtc_peerconnection_factory.h"
#include
#include
#include
#if defined(_WIN32) || defined(WINDOWS)
#include "win_sys_audio_capturer.h"
#elif defined(linux) || defined(LINUX)
#include "linux_sys_audio_capturer.h"
#else
#pragma message("SysAudioSource is only available on Windows and Linux (stub)")
#endif
namespace flutter_webrtc_plugin {
using namespace libwebrtc;
#if defined(_WIN32) || defined(WINDOWS)
using PlatformSysAudioCapturer = WinSysAudioCapturer;
#elif defined(linux) || defined(LINUX)
using PlatformSysAudioCapturer = LinuxSysAudioCapturer;
#endif
class SysAudioSource : public RTCAudioSource {
public:
SysAudioSource(scoped_refptr factory,
const std::string& audio_source_label = "sys_audio_input");
~SysAudioSource() override;
bool Initialize(const std::string& device_id = "");
bool StartCapture();
void StopCapture();
bool IsCapturing() const;
void CaptureFrame(const void* audio_data, int bits_per_sample,
int sample_rate, size_t number_of_channels,
size_t number_of_frames) override {
if (enable_pcm_recording_ && pcm_file_.is_open()) {
pcm_file_.write(static_cast<const char*>(audio_data),
bits_per_sample / 8 * number_of_channels * number_of_frames);
pcm_file_.flush();
total_frames_recorded_ += number_of_frames;
}
// std::cout << "sink size:" << rtc_audio_source_->GetSinkSize() << std::endl;
// std::cout << bits_per_sample << " " << sample_rate << " " << number_of_channels << " " << number_of_frames << std::endl;
rtc_audio_source_->CaptureFrame(audio_data, bits_per_sample, sample_rate,
number_of_channels, number_of_frames);
} else {
std::cout << "rtc_audio_source_ is null" << std::endl;
}
}
SourceType GetSourceType() const override {
return SourceType::kCustom;
}
scoped_refptr rtc_audio_source() {
return rtc_audio_source_;
}
int GetSinkSize() override {
return rtc_audio_source_->GetSinkSize();
}
void EnablePcmRecording(bool enable, const std::string& file_path) {
if (enable) {
pcm_file_.open(file_path, std::ios::binary);
if (pcm_file_.is_open()) {
enable_pcm_recording_ = true;
total_frames_recorded_ = 0;
std::cout << "PCM recording started: " << file_path << std::endl;
} else {
std::cout << "Failed to open PCM file: " << file_path << std::endl;
}
} else {
enable_pcm_recording_ = false;
if (pcm_file_.is_open()) {
pcm_file_.close();
std::cout << "PCM recording stopped. Total frames: "
<< total_frames_recorded_ << std::endl;
}
}
}
bool IsPcmRecordingEnabled() const {
return enable_pcm_recording_;
}
private:
static void OnAudioDataCallback(const void* audio_data,
int bits_per_sample,
int sample_rate,
size_t number_of_channels,
size_t number_of_frames,
void* user_data);
std::unique_ptr capturer_;
scoped_refptr factory_;
scoped_refptr rtc_audio_source_;
std::string audio_source_label_;
bool enable_pcm_recording_ = false;
std::ofstream pcm_file_;
size_t total_frames_recorded_ = 0;
};
} // namespace flutter_webrtc_plugin
#endif // SYS_AUDIO_SOURCE_HXX
#include "sys_audio_source.h"
#include
namespace flutter_webrtc_plugin {
SysAudioSource::SysAudioSource(
scoped_refptr factory,
const std::string& audio_source_label)
: factory_(factory), audio_source_label_(audio_source_label) {
std::cout << "Creating SysAudioSource: " << audio_source_label;
RTCAudioOptions options;
options.echo_cancellation = false;
options.noise_suppression = false;
options.auto_gain_control = false;
options.highpass_filter = false;
rtc_audio_source_ = factory_->CreateAudioSource(
audio_source_label.c_str(),
RTCAudioSource::SourceType::kCustom,
options);
if (rtc_audio_source_) {
capturer_ = std::make_unique();
} else {
std::cout << "Failed to create RTCAudioSource";
}
}
SysAudioSource::~SysAudioSource() {
std::cout << "Destroying SysAudioSource";
StopCapture();
rtc_audio_source_ = nullptr;
}
bool SysAudioSource::Initialize(const std::string& device_id) {
if (!capturer_) {
std::cout << "Capturer not initialized";
return false;
}
bool result = capturer_->Initialize(device_id);
if (result) {
std::cout << "SysAudioSource initialized with device: "
<< (device_id.empty() ? "default" : device_id);
} else {
std::cout << "Failed to initialize SysAudioSource (platform may not support it)";
}
return result;
}
bool SysAudioSource::StartCapture() {
if (!capturer_) {
std::cout << "Cannot start capture - capturer is null";
return false;
}
if (capturer_->IsCapturing()) {
std::cout << "Already capturing";
return true;
}
bool result = capturer_->StartCapture();
if (result) {
std::cout << "Started sys audio capture";
} else {
std::cout << "Failed to start sys audio capture (platform may not support it)";
}
return result;
}
void SysAudioSource::StopCapture() {
if (capturer_ && capturer_->IsCapturing()) {
capturer_->StopCapture();
std::cout << "Stopped sys audio capture";
}
}
bool SysAudioSource::IsCapturing() const {
return capturer_ ? capturer_->IsCapturing() : false;
}
void SysAudioSource::OnAudioDataCallback(const void* audio_data,
int bits_per_sample,
int sample_rate,
size_t number_of_channels,
size_t number_of_frames,
void* user_data) {
SysAudioSource* self = static_cast<SysAudioSource*>(user_data);
if (self) {
self->CaptureFrame(audio_data, bits_per_sample, sample_rate,
number_of_channels, number_of_frames);
}
}
} // namespace flutter_webrtc_plugin
sink可以触发,向里面发送数据但是远程的peerconection无法接收到。
flutter: report => {
flutter: id: T01,
flutter: type: transport,
flutter: timestamp: 1774874753187447.0,
flutter: values => {
flutter: bytesReceived : 721,
flutter: bytesSent : 698,
flutter: dtlsCipher : TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
flutter: dtlsRole : client,
flutter: dtlsState : connected,
flutter: iceLocalUsernameFragment : Aq26,
flutter: iceRole : controlled,
flutter: iceState : connected,
flutter: localCertificateId : CF3C:1A:91:3D:2C:C7:4E:71:B6:79:72:75:B9:E6:CD:FC:33:A9:03:4F:70:BA:33:6B:41:9B:15:F3:4C:09:1E:5D,
flutter: packetsReceived : 2,
flutter: packetsSent : 2,
flutter: remoteCertificateId : CF8D:2D:B5:B8:AD:27:B2:F7:8D:E2:10:DA:04:FE:B6:4B:01:13:26:BC:DC:35:9E:68:2F:A4:24:C1:87:74:55:99,
flutter: selectedCandidatePairChanges : 1,
flutter: selectedCandidatePairId : CPKxHVStaL_cIePVcEY,
flutter: srtpCipher : AES_CM_128_HMAC_SHA1_80,
flutter: tlsVersion : FEFD,
flutter: }
flutter: }
flutter: report => {
flutter: id: CF3C:1A:91:3D:2C:C7:4E:71:B6:79:72:75:B9:E6:CD:FC:33:A9:03:4F:70:BA:33:6B:41:9B:15:F3:4C:09:1E:5D,
flutter: type: certificate,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: base64Certificate : MIIBFTCBvaADAgECAgkAxLzdGpK1SoQwCgYIKoZIzj0EAwIwETEPMA0GA1UEAwwGV2ViUlRDMB4XDTI2MDMyOTEyNDUwNFoXDTI2MDQyOTEyNDUwNFowETEPMA0GA1UEAwwGV2ViUlRDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESl+GWmPHfWGcotiy2c1NvxvPM9ahDIOXkzyW4nwx06c+BW3vJv1xVKu5488BdQVQVkld+tHugkBf7gL3A0zCyDAKBggqhkjOPQQDAgNHADBEAiB8viLhWqrVzQk983MOMc1yuTZ4GaRUVwLIJ7TgKpgyCwIgScdrM6/zKrvGwlwMJ3rp4QZHJBS9+nbW2gv/vVIMRx8=,
flutter: fingerprint : 3C:1A:91:3D:2C:C7:4E:71:B6:79:72:75:B9:E6:CD:FC:33:A9:03:4F:70:BA:33:6B:41:9B:15:F3:4C:09:1E:5D,
flutter: fingerprintAlgorithm : sha-256,
flutter: }
flutter: }
flutter: report => {
flutter: id: CF8D:2D:B5:B8:AD:27:B2:F7:8D:E2:10:DA:04:FE:B6:4B:01:13:26:BC:DC:35:9E:68:2F:A4:24:C1:87:74:55:99,
flutter: type: certificate,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: base64Certificate : MIIBFjCBvKADAgECAggDOiiGHpaqXjAKBggqhkjOPQQDAjARMQ8wDQYDVQQDDAZXZWJSVEMwHhcNMjYwMzI5MTI0NTA0WhcNMjYwNDI5MTI0NTA0WjARMQ8wDQYDVQQDDAZXZWJSVEMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATxCKelMmxcjXOjbLbfvyKR2kzJz1uO/5yOdho8sUcgCsWdC3zJYgupb8CqsHUqhFY5EI15SYw5PxFd7ssSKuY8MAoGCCqGSM49BAMCA0kAMEYCIQD4gf2AfJBo0l+pdNTLDdZZ+/QxXWpkAkQWncothgcLiwIhAM7p4AbvM6agIHau45c3ve+o5o5EN8vMXPFDq6RS6Xqo,
flutter: fingerprint : 8D:2D:B5:B8:AD:27:B2:F7:8D:E2:10:DA:04:FE:B6:4B:01:13:26:BC:DC:35:9E:68:2F:A4:24:C1:87:74:55:99,
flutter: fingerprintAlgorithm : sha-256,
flutter: }
flutter: }
flutter: report => {
flutter: id: CPKxHVStaL_cIePVcEY,
flutter: type: candidate-pair,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: availableOutgoingBitrate : 2000000.0,
flutter: bytesDiscardedOnSend : 0,
flutter: bytesReceived : 721,
flutter: bytesSent : 698,
flutter: consentRequestsSent : 21,
flutter: currentRoundTripTime : 0.0,
flutter: lastPacketReceivedTimestamp : 1774874707186.0,
flutter: lastPacketSentTimestamp : 1774874707182.0,
flutter: localCandidateId : IKxHVStaL,
flutter: nominated : true,
flutter: packetsDiscardedOnSend : 0,
flutter: packetsReceived : 2,
flutter: packetsSent : 2,
flutter: priority : 9114756780654345726,
flutter: remoteCandidateId : IcIePVcEY,
flutter: requestsReceived : 22,
flutter: requestsSent : 22,
flutter: responsesReceived : 22,
flutter: responsesSent : 22,
flutter: state : succeeded,
flutter: totalRoundTripTime : 0.004,
flutter: transportId : T01,
flutter: writable : true,
flutter: }
flutter: }
flutter: report => {
flutter: id: IKxHVStaL,
flutter: type: local-candidate,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: address : 10.1.2.211,
flutter: candidateType : host,
flutter: foundation : 3460999637,
flutter: ip : 10.1.2.211,
flutter: isRemote : false,
flutter: networkAdapterType : wifi,
flutter: networkType : wifi,
flutter: port : 64627,
flutter: priority : 2122194687,
flutter: protocol : udp,
flutter: transportId : T01,
flutter: usernameFragment : Aq26,
flutter: vpn : false,
flutter: }
flutter: }
flutter: report => {
flutter: id: IT01A296816917,
flutter: type: inbound-rtp,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: audioLevel : 0.0,
flutter: bytesReceived : 0,
flutter: concealedSamples : 0,
flutter: concealmentEvents : 0,
flutter: delayedPacketOutageSamples : 0,
flutter: fecPacketsDiscarded : 0,
flutter: fecPacketsReceived : 0,
flutter: headerBytesReceived : 0,
flutter: insertedSamplesForDeceleration : 0,
flutter: interruptionCount : 0,
flutter: jitter : 0.0,
flutter: jitterBufferDelay : 0.0,
flutter: jitterBufferEmittedCount : 0,
flutter: jitterBufferFlushes : 0,
flutter: jitterBufferMinimumDelay : 0.0,
flutter: jitterBufferTargetDelay : 0.0,
flutter: kind : audio,
flutter: mid : 0,
flutter: packetsDiscarded : 0,
flutter: packetsLost : 0,
flutter: packetsReceived : 0,
flutter: relativePacketArrivalDelay : 0.0,
flutter: removedSamplesForAcceleration : 0,
flutter: silentConcealedSamples : 0,
flutter: ssrc : 296816917,
flutter: totalAudioEnergy : 0.0,
flutter: totalInterruptionDuration : 0.0,
flutter: totalProcessingDelay : 0.0,
flutter: totalSamplesDuration : 47.019999999999214,
flutter: totalSamplesReceived : 0,
flutter: trackIdentifier : 6dada39b-21bc-4597-9fd4-4e88382ac1a4,
flutter: transportId : T01,
flutter: }
flutter: }
flutter: report => {
flutter: id: IcIePVcEY,
flutter: type: remote-candidate,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: address : 10.1.2.211,
flutter: candidateType : host,
flutter: foundation : 1706040316,
flutter: ip : 10.1.2.211,
flutter: isRemote : true,
flutter: port : 65133,
flutter: priority : 2122194687,
flutter: protocol : udp,
flutter: transportId : T01,
flutter: usernameFragment : DiET,
flutter: }
flutter: }
flutter: report => {
flutter: id: T01,
flutter: type: transport,
flutter: timestamp: 1774874754187561.0,
flutter: values => {
flutter: bytesReceived : 721,
flutter: bytesSent : 698,
flutter: dtlsCipher : TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
flutter: dtlsRole : client,
flutter: dtlsState : connected,
flutter: iceLocalUsernameFragment : Aq26,
flutter: iceRole : controlled,
flutter: iceState : connected,
flutter: localCertificateId : CF3C:1A:91:3D:2C:C7:4E:71:B6:79:72:75:B9:E6:CD:FC:33:A9:03:4F:70:BA:33:6B:41:9B:15:F3:4C:09:1E:5D,
flutter: packetsReceived : 2,
flutter: packetsSent : 2,
flutter: remoteCertificateId : CF8D:2D:B5:B8:AD:27:B2:F7:8D:E2:10:DA:04:FE:B6:4B:01:13:26:BC:DC:35:9E:68:2F:A4:24:C1:87:74:55:99,
flutter: selectedCandidatePairChanges : 1,
flutter: selectedCandidatePairId : CPKxHVStaL_cIePVcEY,
flutter: srtpCipher : AES_CM_128_HMAC_SHA1_80,
flutter: tlsVersion : FEFD,
flutter: }
flutter: }
flutter: Have a Sender of kind:audio
flutter: Setting direction and replacing track with null
flutter: LocalRenegotiationNeeded
LocalAudioSource RemoveSink1
MediaStreamForId: b4edfbb4-cce1-4d9f-aa60-8dc0958ab556
flutter: local pc: onSignalingState(RTCSignalingState.RTCSignalingStateHaveLocalOffer), state2(RTCSignalingState.RTCSignalingStateHaveLocalOffer)
flutter: remote pc: onSignalingState(RTCSignalingState.RTCSignalingStateHaveRemoteOffer), state2(RTCSignalingState.RTCSignalingStateHaveRemoteOffer)
flutter: remote pc: onSignalingState(RTCSignalingState.RTCSignalingStateStable), state2(RTCSignalingState.RTCSignalingStateStable)
MediaStreamForId: b4edfbb4-cce1-4d9f-aa60-8dc0958ab556
bytesReceived 的值没有什么变化,表示远端没有接收到数据(我可以保证是一直发送数据的 ondata方法一直被调用)