diff --git a/README.md b/README.md index c1d32c0..4f93d4e 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ |模块|名称|描述| |:--|:--|:--| -|taoyao-client-web|Web终端|Web终端| +|taoyao-client-web|H5终端|浏览器终端| |taoyao-client-media|媒体终端|媒体服务| |taoyao-client-android|安卓终端|安卓终端| |taoyao-signal-server|信令服务|终端信令控制| @@ -34,7 +34,15 @@ |Mediasoup|支持|完成|视频房间(会话)| |控制|支持|完成|完整控制信令| -### 安卓终端功能 +## Media终端功能 + +|功能|是否支持|是否实现|描述| +|:--|:--|:--|:--| +|Mediasoup|支持|完成|视频房间(会议)| +|录像|支持|未完成|录像| +|混音|支持|未完成|多路混音| + +### Android终端功能 |功能|是否支持|是否实现|描述| |:--|:--|:--|:--| @@ -42,7 +50,7 @@ |Mediasoup|支持|完成|视频房间(会议)| |控制|支持|完成|部分控制信令| |拍照|支持|完成|拍照| -|录像|支持|完成|录制| +|录像|支持|完成|录像| |混音|支持|完成|多路混音| |水印|支持|完成|视频水印| diff --git a/docs/Deploy.md b/docs/Deploy.md index 18b06bc..3762f21 100644 --- a/docs/Deploy.md +++ b/docs/Deploy.md @@ -3,7 +3,7 @@ ## 整体环境 ``` -CentOS:CentOS Linux release 7.9.2009 (Core) +CentOS = CentOS Linux release 7.9.2009 (Core) git >= 1.8.0 pm2 >= 5.2.0 Java >= 17.0.0 @@ -24,6 +24,12 @@ wget /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7. yum makecache ``` +## 更新依赖 + +``` +yum install zlib-devel libffi-devel openssl-devel +``` + ## 优化Linux句柄数量 ``` @@ -126,7 +132,11 @@ tar -Jxvf node-v16.19.0-linux-x64.tar.xz ln -sf /data/dev/nodejs/node-v16.19.0-linux-x64/bin/npm /usr/local/bin/ ln -sf /data/dev/nodejs/node-v16.19.0-linux-x64/bin/node /usr/local/bin/ +# 镜像 +npm config set registry https://registry.npm.taobao.org + # 验证 +npm config get registry npm -v node -v ``` @@ -205,9 +215,6 @@ mvn -version ## 安装Python ``` -# 依赖 -yum install zlib-devel libffi-devel openssl-devel - # 下载 mkdir -p /data/dev/python cd /data/dev/python @@ -459,3 +466,14 @@ openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.p12 # 原始密码:-srcstorepass 123456 # 设置密码:-deststorepass 123456 ``` + +## Debian + +如果使用`Debian`大部分命令都是通用的,使用`apt`替换`yum`即可,不用处理`Yum`中`Python`的冲突。 + +``` +# 常用工具 +apt-get install vim wget net-tools +# 依赖软件 +apt-get install libssl-dev zlib1g-dev build-essential +``` diff --git a/docs/TODO.md b/docs/TODO.md index 13b7fb6..7491693 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -12,9 +12,9 @@ 单例变量 单例静态函数 构造函数 -成员函数(public/protected/private) +成员函数(`public/protected/private`) 静态成员函数 -getter/setter +`getter/setter` ## 日常任务 @@ -33,10 +33,11 @@ getter/setter * 开机自启 * 录制底噪 * 分辨率调整 +* 服务端录制 * 降低视频录制大小 * 防止重复邀请拉取 * 查询消费者生产者信息 -* 浏览器WebRTC监控页面关闭 +* 浏览器WebRTC监控页面关闭:`chrome://webrtc-internals/` ## 完成任务 diff --git a/taoyao-client-android/taoyao/client/src/main/java/com/acgist/taoyao/client/MainActivity.java b/taoyao-client-android/taoyao/client/src/main/java/com/acgist/taoyao/client/MainActivity.java index 26d75e4..3202638 100644 --- a/taoyao-client-android/taoyao/client/src/main/java/com/acgist/taoyao/client/MainActivity.java +++ b/taoyao-client-android/taoyao/client/src/main/java/com/acgist/taoyao/client/MainActivity.java @@ -228,29 +228,6 @@ public class MainActivity extends AppCompatActivity { }); } - /** - * MainHandler - * 后台线程和UI线程关联线程Handler - * - * @author acgist - */ - public class MainHandler extends Handler { - - @Override - public void handleMessage(@NonNull Message message) { - super.handleMessage(message); - Log.d(MainHandler.class.getSimpleName(), "MainHandler消息:" + message.what); - switch (message.what) { - case Config.WHAT_SCREEN_CAPTURE -> MainActivity.this.screenCapture(message); - case Config.WHAT_RECORD -> MainActivity.this.record(message); - case Config.WHAT_NEW_LOCAL_VIDEO, - Config.WHAT_NEW_REMOTE_VIDEO -> MainActivity.this.previewVideo(message); - case Config.WHAT_REMOVE_VIDEO -> MainActivity.this.removePreviewVideo(message); - } - } - - } - /** * 屏幕捕获 * @@ -321,5 +298,28 @@ public class MainActivity extends AppCompatActivity { this.removeLayoutParams.add(surfaceView.getLayoutParams()); } } + + /** + * MainHandler + * 后台线程和UI线程关联线程Handler + * + * @author acgist + */ + public class MainHandler extends Handler { + + @Override + public void handleMessage(@NonNull Message message) { + super.handleMessage(message); + Log.d(MainHandler.class.getSimpleName(), "MainHandler消息:" + message.what); + switch (message.what) { + case Config.WHAT_SCREEN_CAPTURE -> MainActivity.this.screenCapture(message); + case Config.WHAT_RECORD -> MainActivity.this.record(message); + case Config.WHAT_NEW_LOCAL_VIDEO, + Config.WHAT_NEW_REMOTE_VIDEO -> MainActivity.this.previewVideo(message); + case Config.WHAT_REMOVE_VIDEO -> MainActivity.this.removePreviewVideo(message); + } + } + + } } diff --git a/taoyao-client-android/taoyao/media/src/main/cpp/include/Log.hpp b/taoyao-client-android/taoyao/media/src/main/cpp/include/Log.hpp index f4337ef..4453ef8 100644 --- a/taoyao-client-android/taoyao/media/src/main/cpp/include/Log.hpp +++ b/taoyao-client-android/taoyao/media/src/main/cpp/include/Log.hpp @@ -7,7 +7,6 @@ namespace acgist { #include "android/log.h" -// TODO:优化INFO提示 #ifndef LOG_TAG_TAOYAO #define LOG_TAG_TAOYAO "libtaoyao" #define LOG_D(format, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG_TAOYAO, "%s " format, __func__, ##__VA_ARGS__) diff --git a/taoyao-client-android/taoyao/media/src/main/cpp/include/RouterCallback.hpp b/taoyao-client-android/taoyao/media/src/main/cpp/include/RouterCallback.hpp index 0a0bdb1..de66f76 100644 --- a/taoyao-client-android/taoyao/media/src/main/cpp/include/RouterCallback.hpp +++ b/taoyao-client-android/taoyao/media/src/main/cpp/include/RouterCallback.hpp @@ -6,28 +6,133 @@ #include "MediaManager.hpp" #include "mediasoupclient.hpp" +/** + * 路由回调头文件 + */ namespace acgist { + /** + * 路由回调 + */ class RouterCallback { public: + /** + * 回调对象 + */ jobject routerCallback; public: + /** + * @param routerCallback 回调对象 + */ RouterCallback(jobject routerCallback); + /** + * 析构函数 + */ virtual ~RouterCallback(); public: + /** + * 进入房间回调 + * + * @param env JNIEnv + * @param rtpCapabilities RTP协商 + * @param sctpCapabilities SCTP协商 + */ void enterRoomCallback(JNIEnv* env, const std::string& rtpCapabilities, const std::string& sctpCapabilities); + /** + * 关闭房间回调 + * + * @param env JNIEnv + */ void closeRoomCallback(JNIEnv* env); + /** + * 发送通道连接回调 + * + * @param env JNIEnv + * @param transportId 通道ID + * @param dtlsParameters DTLS参数 + */ void sendTransportConnectCallback(JNIEnv* env, const std::string& transportId, const std::string& dtlsParameters); + /** + * 接收通道连接回调 + * + * @param env JNIEnv + * @param transportId 通道ID + * @param dtlsParameters DTLS参数 + */ void recvTransportConnectCallback(JNIEnv* env, const std::string& transportId, const std::string& dtlsParameters); + /** + * 发送通道生产回调 + * + * @param env JNIEnv + * @param kind 类型 + * @param transportId 通道ID + * @param rtpParameters RTP参数 + * + * @return 生产者ID + */ std::string sendTransportProduceCallback(JNIEnv* env, const std::string& kind, const std::string& transportId, const std::string& rtpParameters); + /** + * 新建生产者回调 + * + * @param env JNIEnv + * @param kind 生产者类型 + * @param producerId 生产者ID + * @param producerPointer 生产者指针 + * @param producerMediaTrackPointer 媒体Tracker指针 + */ void producerNewCallback(JNIEnv* env, const std::string& kind, const std::string& producerId, mediasoupclient::Producer* producerPointer, webrtc::MediaStreamTrackInterface* producerMediaTrackPointer); + /** + * 关闭生产者回调 + * + * @param env JNIEnv + * @param producerId 生产者ID + */ void producerCloseCallback(JNIEnv* env, const std::string& producerId); + /** + * 暂停生产者回调 + * + * @param env JNIEnv + * @param producerId 生产者ID + */ void producerPauseCallback(JNIEnv* env, const std::string& producerId); + /** + * 恢复生产者回调 + * + * @param env JNIEnv + * @param producerId 生产者ID + */ void producerResumeCallback(JNIEnv* env, const std::string& producerId); + /** + * 新建消费者回调 + * + * @param env JNIEnv + * @param message 信令消息 + * @param consumerPointer 消费者指针 + * @param consumerMediaTrackPointer 媒体Tracker指针 + */ void consumerNewCallback(JNIEnv* env, const std::string& message, mediasoupclient::Consumer* consumerPointer, webrtc::MediaStreamTrackInterface* consumerMediaTrackPointer); + /** + * 关闭消费者回调 + * + * @param env JNIEnv + * @param consumerId 消费者ID + */ void consumerCloseCallback(JNIEnv* env, const std::string& consumerId); + /** + * 暂停消费者回调 + * + * @param env JNIEnv + * @param consumerId 消费者ID + */ void consumerPauseCallback(JNIEnv* env, const std::string& consumerId); + /** + * 恢复消费者回调 + * + * @param env JNIEnv + * @param consumerId 消费者ID + */ void consumerResumeCallback(JNIEnv* env, const std::string& consumerId); + }; } \ No newline at end of file diff --git a/taoyao-client-android/taoyao/media/src/main/cpp/webrtc/MediaManager.cpp b/taoyao-client-android/taoyao/media/src/main/cpp/webrtc/MediaManager.cpp index e5fbc10..c921b1b 100644 --- a/taoyao-client-android/taoyao/media/src/main/cpp/webrtc/MediaManager.cpp +++ b/taoyao-client-android/taoyao/media/src/main/cpp/webrtc/MediaManager.cpp @@ -8,19 +8,30 @@ namespace acgist { JavaVMAttachArgs args; args.name = name; args.version = JNI_VERSION_1_6; + if(taoyaoJavaVM == nullptr) { + LOG_W("绑定线程失败:JavaVM为空"); + return; + } taoyaoJavaVM->AttachCurrentThreadAsDaemon(env, &args); } void unbindJavaThread() { + if(taoyaoJavaVM == nullptr) { + LOG_W("解绑线程失败:JavaVM为空"); + return; + } taoyaoJavaVM->DetachCurrentThread(); } /** - * 非常重要 + * 加载库文件时加载WebRTC,JNI自动调用。 */ - extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* javaVM, void* reserved) { + extern "C" JNIEXPORT jint JNICALL + JNI_OnLoad(JavaVM* javaVM, void* reserved) { + LOG_I("加载WebRTC"); taoyaoJavaVM = javaVM; - // JNIEnv* env = webrtc::jni::GetEnv(); +// JNIEnv* env = webrtc::jni::GetEnv(); + // 下面非常重要 webrtc::jni::InitGlobalJniVariables(javaVM); return JNI_VERSION_1_6; } @@ -28,7 +39,7 @@ namespace acgist { extern "C" JNIEXPORT void JNICALL Java_com_acgist_taoyao_media_MediaManager_nativeInit(JNIEnv* env, jobject me) { std::string version = mediasoupclient::Version(); - LOG_I("加载MediasoupClient", version.data()); + LOG_I("加载MediasoupClient %s", version.data()); mediasoupclient::Initialize(); // => { spatialLayers: 2, temporalLayers: 3 } // mediasoupclient::parseScalabilityMode("L2T3"); diff --git a/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/MediaManager.java b/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/MediaManager.java index 8af4ad3..6e8853e 100644 --- a/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/MediaManager.java +++ b/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/MediaManager.java @@ -967,7 +967,14 @@ public final class MediaManager { } } + /** + * 加载MediasoupClient + */ private native void nativeInit(); + + /** + * 关闭MediasoupClient + */ private native void nativeStop(); } diff --git a/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/RouterCallback.java b/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/RouterCallback.java index 9315dbb..f699103 100644 --- a/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/RouterCallback.java +++ b/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/RouterCallback.java @@ -7,18 +7,105 @@ package com.acgist.taoyao.media; */ public interface RouterCallback { + /** + * 进入房间回调 + * + * @param rtpCapabilities RTP协商 + * @param sctpCapabilities SCTP协商 + */ default void enterRoomCallback(String rtpCapabilities, String sctpCapabilities) {}; + + /** + * 关闭房间回调 + */ default void closeRoomCallback() {}; + + /** + * 发送通道连接回调 + * + * @param transportId 通告ID + * @param dtlsParameters DTLS参数 + */ default void sendTransportConnectCallback(String transportId, String dtlsParameters) {}; + + /** + * 接收通道连接回调 + * + * @param transportId 通道ID + * @param dtlsParameters DTLS参数 + */ default void recvTransportConnectCallback(String transportId, String dtlsParameters) {}; + + /** + * 发送通道生产回调 + * + * @param kind 类型 + * @param transportId 通道ID + * @param rtpParameters RTP参数 + * + * @return 生产者ID + */ default String sendTransportProduceCallback(String kind, String transportId, String rtpParameters) { return null; }; + + /** + * 新建生产者回调 + * + * @param kind 生产者类型 + * @param producerId 生产者ID + * @param producerPointer 生产者指针 + * @param producerMediaTrackPointer 媒体Tracker指针 + */ default void producerNewCallback(String kind, String producerId, long producerPointer, long producerMediaTrackPointer) {}; + + /** + * 关闭生产者回调 + * + * @param producerId 生产者ID + */ default void producerCloseCallback(String producerId) {}; + + /** + * 暂停生产者回调 + * + * @param producerId 生产者ID + */ default void producerPauseCallback(String producerId) {}; + + /** + * 恢复生产者回调 + * + * @param producerId 生产者ID + */ default void producerResumeCallback(String producerId) {}; + + /** + * 新建消费者回调 + * + * @param message 信令消息 + * @param consumerPointer 消费者指针 + * @param consumerMediaTrackPointer 媒体Tracker指针 + */ default void consumerNewCallback(String message, long consumerPointer, long consumerMediaTrackPointer) {}; + + /** + * 关闭消费者回调 + * + * @param consumerId 消费者ID + */ default void consumerCloseCallback(String consumerId) {}; + + /** + * 暂停消费者回调 + * + * @param consumerId 消费者ID + */ default void consumerPauseCallback(String consumerId) {}; + + /** + * 恢复消费者回调 + * + * @param consumerId 消费者ID + */ default void consumerResumeCallback(String consumerId) {}; }