我想使用自定义视频源通过 WebRTC Android 实现直播视频。如果我理解正确,现有实现仅支持 Android 手机上的前置和后置摄像头。以下类与此场景相关:
目前在 Android 手机上使用前置摄像头,我正在执行以下步骤:
CameraEnumerator enumerator = new Camera1Enumerator(false);
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
VideoSource videoSource = peerConnectionFactory.createVideoSource(false);
videoCapturer.initialize(surfaceTextureHelper, this.getApplicationContext(), videoSource.getCapturerObserver());
VideoTrack localVideoTrack = peerConnectionFactory.createVideoTrack(VideoTrackID, videoSource);
Run Code Online (Sandbox Code Playgroud)
我有一个回调处理程序,它从自定义视频源接收字节数组中的视频缓冲区:
public void onReceive(byte[] videoBuffer, int size) {}
Run Code Online (Sandbox Code Playgroud)
我怎样才能发送这个字节数组缓冲区?我不确定解决方案,但我想我必须实现自定义VideoCapturer?
这个问题可能是相关的,尽管我没有使用 libjingle 库,只使用原生 WebRTC Android 包。
类似的问题/文章:
我使用 getStats(RTCStatsCollectorCallback callback) API 来获取“发送比特率”和“接收比特率”值。
我面临两个问题:
1)。当会议中只有 1 个用户时,有时“发送的比特率”值会变得非常大(以 mbps 为单位)。
2)。当会议中只有 2 个(或更多)用户并且一个用户(不是主持人)共享他的屏幕时,返回值波动太大(意味着有时它非常小,有时它非常大(以 mbps 为单位))。
peerConnection.getStats(new RTCStatsCollectorCallback() {
@Override
public void onStatsDelivered(RTCStatsReport rtcStatsReport) {
for (Map.Entry<String, RTCStats> e : rtcStatsReport.getStatsMap().entrySet()) {
if (e.getKey().startsWith("RTCInboundRTPAudioStream") ||
e.getKey().startsWith("RTCInboundRTPVideoStream")) {
String receivedBitrate = null;
if (e.getValue().getMembers().get("bytesReceived") != null) {
receivedBitrate = ("" +
e.getValue().getMembers().get("bytesReceived"));
}
}
if (e.getKey().startsWith("RTCOutboundRTPAudioStream") ||
e.getKey().startsWith("RTCOutboundRTPVideoStream")) {
String sentBitrate = null;
if (e.getValue().getMembers().get("bytesSent") != null) {
sentBitrate = ("" +
e.getValue().getMembers().get("bytesSent"));
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想我在从新的 getStats() API …
尝试通过 WebRtc 流式传输位图。我的 Capturer 类大致如下所示:
public class BitmapCapturer implements VideoCapturer, VideoSink {
private Capturer capturer;
private int width;
private int height;
private SurfaceTextureHelper textureHelper;
private Context appContext;
@Nullable
private CapturerObserver capturerObserver;
@Override
public void initialize(SurfaceTextureHelper surfaceTextureHelper,
Context context, CapturerObserver capturerObserver) {
if (capturerObserver == null) {
throw new RuntimeException("capturerObserver not set.");
} else {
this.appContext = context;
this.textureHelper = surfaceTextureHelper;
this.capturerObserver = capturerObserver;
this.capturer = new Capturer();
this.textureHelper.startListening(this);
}
}
@Override
public void startCapture(int width, int height, int fps) { …Run Code Online (Sandbox Code Playgroud) android surfaceview render-to-texture opengl-es-2.0 webrtc-android
在某些移动设备(如摩托罗拉 One Power - Android 10、红米 Note 5 Pro - Android 7.1.2)中,手机扬声器的声音通过手机麦克风进入会议并产生回声。仅当电话扬声器处于开启状态时才会出现此回声问题。
我使用了 AudioManager 的 MODE_IN_COMMUNICATION 模式:
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
Run Code Online (Sandbox Code Playgroud)
此外,在音频约束下使用 PeerConnectionFactory 的 createAudioSource() API 创建音频源:
audioConstraints = new MediaConstraints();
audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googEchoCancellation", "true"));
audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googAutoGainControl", "true"));
audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googHighpassFilter", "true"));
audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googNoiseSuppression", "true"));
Run Code Online (Sandbox Code Playgroud)
任何解决问题的帮助或指导将不胜感激。
我面临着这个奇怪的问题,SurfaceViewRenderer每当我在横向/反向横向/传感器横向中运行活动时,预览就会变成空白。奇怪的问题是,在某些手机中,视频预览以反向横向模式工作,而在某些手机中以横向模式工作。例如,当我在 中运行 Activity 时Android 5.0,横向模式下的视频预览工作正常,但在反向横向模式下则不行。然后我尝试在我正在运行的一加手机上执行相同的操作Android 10。这里 SurfaceViewRenderer 中的视频预览在反向横向模式下工作正常,但在横向模式下则不然。
注意:即使预览变为空白,远程流也可以正常工作,没有任何问题,只有视频预览不起作用。它以某种方式无法更新,SurfaceViewRenderer但没有问题流向远程参与者。
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.session.activities.LiveSessionActivity">
<org.webrtc.SurfaceViewRenderer
android:id="@+id/localGLSurfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
<View
android:id="@+id/vBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.4"
android:background="@android:color/black"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/localGLSurfaceView"
app:layout_constraintEnd_toEndOf="@+id/localGLSurfaceView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/localGLSurfaceView"
app:layout_constraintTop_toTopOf="@+id/localGLSurfaceView"
app:layout_constraintVertical_bias="0.0" />
<View
android:id="@+id/vShadow"
android:layout_width="wrap_content"
android:layout_height="@dimen/_42sdp"
android:background="@drawable/ic_rectangle_shadow"
app:layout_constraintEnd_toEndOf="@+id/localGLSurfaceView"
app:layout_constraintStart_toStartOf="@+id/localGLSurfaceView"
app:layout_constraintTop_toTopOf="@+id/localGLSurfaceView" />
<ImageView
android:id="@+id/ivBackButton"
android:layout_width="@dimen/_8sdp"
android:layout_height="@dimen/_13sdp"
android:layout_marginStart="@dimen/_12sdp"
android:layout_marginTop="@dimen/_16sdp"
android:src="@drawable/ic_back"
app:layout_constraintStart_toStartOf="@+id/localGLSurfaceView"
app:layout_constraintTop_toTopOf="@+id/localGLSurfaceView" />
<TextView
android:id="@+id/tvLiveClassName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/_12sdp"
android:text="Live Class 10"
android:textColor="@android:color/white"
android:textSize="@dimen/medium_text"
app:layout_constraintBottom_toBottomOf="@+id/ivBackButton"
app:layout_constraintStart_toEndOf="@+id/ivBackButton"
app:layout_constraintTop_toTopOf="@+id/ivBackButton" />
<TextView
android:id="@+id/tvCountDown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5"
android:textColor="@android:color/white" …Run Code Online (Sandbox Code Playgroud) 我在 android 和 iOs 之间调用时使用 SurfaceViewRenderer 显示远程视频轨道时遇到问题(android <-> android 和 ios<->ios 也可以工作)
Android 上的远程视频视图会在几秒钟后冻结,但音频仍然有效(iOS 没问题)。
可能是iOS的H264编解码器引起的问题,但我按照最新的代码进行解码和编码PeerConnection,所以我仍然卡在这里。
下面是我的代码:
创造PeerConnectionFactory:
PeerConnectionFactory.initialize(
PeerConnectionFactory.InitializationOptions.builder(activity.getApplicationContext())
.setEnableInternalTracer(true)
.setEnableVideoHwAcceleration(true, true)
.createInitializationOptions());
Run Code Online (Sandbox Code Playgroud)
解码和编码
private void tryingToCreatePeerConnectionFactory(EglBase eglBase) {
final PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
final DefaultVideoEncoderFactory encoderFactory = new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true);
final DefaultVideoDecoderFactory decoderFactory = new DefaultVideoDecoderFactory(eglBase.getEglBaseContext());
peerConnectionFactory = PeerConnectionFactory.builder().setOptions(options).
setVideoDecoderFactory(decoderFactory).
setVideoEncoderFactory(encoderFactory).
createPeerConnectionFactory();
}
Run Code Online (Sandbox Code Playgroud)
SDP内容
v=0
o=- 3807425029370800822 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS ARDAMS
m=audio 9 …Run Code Online (Sandbox Code Playgroud) 我试图MediaStream在RecyclerView. 目前,我的同伴MediaStream在我们最初的握手时给了我所有的对象,我能够在一个具有自定义TextureView. 当我获得大量要滚动的流时,就会出现问题。在滚动足够多的列表项后,我最终崩溃了。
MediaStream#dispose()当我的列表项被回收时,我尝试使用该功能。这似乎避免了使用过多解码器资源的问题,但也使得流无法再次查看。如果用户想要滚动到已设置的流,我的应用程序异常崩溃MediaStreamTrack has been disposed.试图启用时MediaStream的VideoTrack。
我希望从视频轨道中删除接收器videoTrack?.removeSink(cameraStreamView)以及release()在我的 TextureView 中调用EglRenderer 上的函数的组合足以清理onViewRecycled().
private fun destroyCameraStream() {
videoTrack?.removeSink(cameraStreamView)
cameraStreamView.release()
}
fun release() {
eglRenderer.release()
}
Run Code Online (Sandbox Code Playgroud)
但是,在向下滚动列表足够远后,我收到错误:
Unable to instantiate codec 'OMX.qcom.video.decoder.avc' with err 0xfffffff4.我认为这是由于我没有完全清理和释放我的编解码器,因为我在旋转它们的过程中没有充分利用资源。
有谁知道是否有某个函数可以调用以正确清理MediaStream资源/用于解码它们的编解码器?有没有关于这种情况的文件?
谢谢!
我正在尝试在 WebRTC 的帮助下将屏幕截图的视频发送到 mediasoup。WebRTC 库中有一个类:ScreenCapturerAndroid。它有效,但在某些设备上的性能非常糟糕。特别是如果我使用 HD 或更好的显示分辨率。
在计算器上我找到了一个建议,以呼叫setEnableVideoHwAcceleration(真)和setVideoHwAccelerationOptions() 。但在较新版本的 WebRTC 库中,这些方法已被删除。
这是我的代码:
// ...
PeerConnectionFactory.Builder builder = PeerConnectionFactory.builder();
builder.setOptions(null);
EglBase.Context eglContext = EglUtils.getRootEglBaseContext();
VideoEncoderFactory encoderFactory =
new DefaultVideoEncoderFactory(
eglContext, true /* enableIntelVp8Encoder */, true);
PeerConnectionFactory.InitializationOptions initializationOptions =
PeerConnectionFactory.InitializationOptions.builder(context)
// .setEnableVideoHwAcceleration(true) // <-- does not work any more
.createInitializationOptions();
PeerConnectionFactory.initialize(initializationOptions);
mPeerConnectionFactory =
builder
.setVideoEncoderFactory(encoderFactory)
.createPeerConnectionFactory();
Run Code Online (Sandbox Code Playgroud)
我的问题是:如何使用较新的 WebRTC 库版本为屏幕捕获启用视频硬件加速。
将 Chrome 更新到最新的 v89(2021 年 3 月 9 日发布)后,SDP 报价的“答复”不会从 Android/iOS 应用程序发送到 Web 应用程序(在 Windows/Mac/Linux 上运行)。
它在 Chrome v88 及更低版本上运行良好。
提供 SDP :
o=- 3986944572502207628 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=extmap-allow-mixed
a=msid-semantic: WMS ER6BzrTgSfzSmlbwz6YLSUR0vFQmlQp6f0ew
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:l4+m
a=ice-pwd:Pi7zEzH/c5fFzvNAn0giR5CJ
a=ice-options:trickle
a=fingerprint:sha-256 5F:A3:0C:CE:24:0C:7B:F3:1D:CE:B4:B3:CE:AF:71:24:44:53:14:5B:ED:29:FF:C1:03:C2:5B:4C:E0:87:B8:DF
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 …Run Code Online (Sandbox Code Playgroud) 我已经创建了从一台设备到另一台设备的 WebRTC 会话,该设备应该能够控制音乐流的音量,但 WebRTC 最初设计用于传输 voice_call,因此使用 voice_call 通道并使用通话音量控制对于非通话应用程序。
我尝试将 WebRTC 源WebRtcAudioTrack中的 STREAM_VOICE_CALL 更改为 STREAM_MUSIC以使用流音乐音量,但唯一的变化是 Android 将其检测为音乐,但音量随通话音量而变化。
webrtc-android ×10
android ×8
webrtc ×8
java ×2
webrtc-ios ×2
exynos ×1
kotlin ×1
mediasoup ×1
microphone ×1
openvidu ×1
streaming ×1
surfaceview ×1
turn ×1