智慧教室无纸化应用场景
智慧教室无纸化方案在多个领域得到了广泛应用,主要体现在教育领域,但随着技术的发展和应用的深入,其应用范围也在逐渐扩大。以下是一些主要的应用领域:
一、教育领域
- 课堂教学:
- 中小学数学课堂:利用电子显示屏和触摸屏技术,解决传统黑板无法高效展示图文并茂内容的问题,提高教学效率。学生可以通过平板电脑进行作答和抢答,增加课堂互动性和参与度。
- 其他学科教学:智慧教室的无纸化方案不仅限于数学,还广泛应用于物理、化学、生物、地理等多门学科。通过虚拟仿真和增强现实技术,学生可以进行虚拟实验和场景模拟,提高学习的趣味性和实效性。
- 教学资源管理:
- 提供个性化学习路径和资源,根据学生的学习需求和能力差异进行精准推送,实现自主学习和提升学习效果。
- 借助云计算和大数据技术,将教学过程数字化和网络化,方便教师和学生进行课前准备、课堂互动和课后作业。
- 教学评价与反馈:
- 通过多样化系统,如分组教学系统和自动跟踪系统,实时监控和记录学生的课堂表现和作业完成情况,为教师提供全面和客观的教学评价依据。
- 教师可以根据即时反馈调整教学策略,确保教学质量的持续提升。
二、企业培训领域
随着企业对员工培训重视程度的提高,智慧教室无纸化方案也逐渐被应用于企业培训中。通过模拟实际工作场景和业务流程,员工可以在虚拟环境中进行实践操作和团队协作,提高培训效果和工作效率。
三、科研机构
科研机构在进行实验研究和数据分析时,往往需要处理大量的数据和文档。智慧教室无纸化方案可以提供高效的数据管理和文档编辑工具,帮助科研人员更加便捷地进行数据整理和分析工作。同时,通过虚拟仿真技术,科研人员还可以进行复杂实验的模拟和预测,降低实验成本和风险。
四、公共服务领域
在图书馆、博物馆等公共服务场所,智慧教室无纸化方案可以应用于展览展示和公众教育活动中。通过数字化展示和互动体验设备,观众可以更加直观地了解展品信息和历史文化知识,提高公共服务的水平和质量。
智慧教室无纸化方案
大牛直播SDK的跨平台Widows、Linux(x86_64|aarch64架构)、Android、iOS的RTMP推拉流模块,服务了业内非常多的智慧教室无纸化业务诉求。
下面就开发者关注的问题,做个答疑:
1. 轻量级RTSP服务还是RTMP?
我们在做智慧教室无纸化同屏的时候,问的最多的是,能不能不要自建服务,直接主讲人或教师端,直接启动轻量级RTSP服务,其他终端拉流,如果是小并发,比如5人内的小范围的同屏,Windows平台走轻量级RTSP无可厚非,如果是30-60甚至100人的会议室,建议走RTMP。
2. 推送分辨率和码率选择
我们接触到好多设备,性能一般,但是屏幕是高分屏,甚至可以采集到4K的,考虑到实时编码和并发环境下,AP的承载能力,一般建议选择适合自己的分辨率码率即可,不要只追求高分辨率高码率,导致组网困难,单个或双通道AP压力大,一般建议控制在1920*1080分辨率内,码率控制在1-5M。
3. 软编码还是硬编码
Windows平台,一般优先考虑软编,因为大多Windows性能瓶颈不太大,超过1080P可以考虑硬编,Android平台建议直接硬编码。
4. 高分屏采集编码效率低怎么办
高分屏,不管是Windows还是Android,采集后的数据,建议先压缩,再编码,Windows平台我们可以设置压缩比例(scale rate),Android平台亦可,比如采集原始屏幕,或者缩放后的屏幕,具体见下图:
/* BackgroudService.java
* Author: daniusdk.com
* WeChat: xinsheng120
*/
private void createScreenEnvironment() {
sreenWindowWidth = mWindowManager.getDefaultDisplay().getWidth();
screenWindowHeight = mWindowManager.getDefaultDisplay().getHeight();
Log.i(TAG, "screenWindowWidth: " + sreenWindowWidth + ",screenWindowHeight: "
+ screenWindowHeight);
if (sreenWindowWidth > 800)
{
if (screen_resolution_type_ == SCREEN_RESOLUTION_STANDARD)
{
scale_rate = SCALE_RATE_HALF;
sreenWindowWidth = align(sreenWindowWidth / 2, 16);
screenWindowHeight = align(screenWindowHeight / 2, 16);
}
else if(screen_resolution_type_ == SCREEN_RESOLUTION_LOW)
{
scale_rate = SCALE_RATE_TWO_FIFTHS;
sreenWindowWidth = align(sreenWindowWidth * 2 / 5, 16);
screenWindowHeight = align(screenWindowHeight * 2 / 5, 16);
}
}
Log.i(TAG, "After adjust mWindowWidth: " + sreenWindowWidth + ", mWindowHeight: " + screenWindowHeight);
int pf = mWindowManager.getDefaultDisplay().getPixelFormat();
Log.i(TAG, "display format:" + pf);
DisplayMetrics displayMetrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(displayMetrics);
mScreenDensity = displayMetrics.densityDpi;
mImageReader = ImageReader.newInstance(sreenWindowWidth,
screenWindowHeight, 0x1, 6);
mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
5. Android横竖屏自动适配
Android平台,如果是pad采集,基本就是横屏采集,如果手机端,需要确保横竖屏模式下都可以正常采集。需要确保横竖屏切换的时候,能自动切换宽高,或者,一开始固定好横竖屏模式也可以。
4. 为什么要考虑补帧
Android的时候,一定的采集模式下,屏幕如果没有变化,不会一直有实时屏幕数据回调下来,这时候,为了保持帧率或数据采集的完整性,建议补帧。
5. 异常网络处理、事件回调机制
网络状态,不管是推送端,还是播放端,都是需要有实时的状态回调,确保客户端可以实时感知网络状态。
backgroudService.SetEventListener(new EventListener() {
@Override
public void onPublisherEventCallback(long handle, int id, long param1, long param2, String param3, String param4, Object param5) {
String publisher_event = "";
switch (id) {
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_STARTED:
publisher_event = "开始..";
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTING:
publisher_event = "连接中..";
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTION_FAILED:
publisher_event = "连接失败..";
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTED:
publisher_event = "连接成功..";
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_DISCONNECTED:
publisher_event = "连接断开..";
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_STOP:
publisher_event = "关闭..";
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_RECORDER_START_NEW_FILE:
publisher_event = "开始一个新的录像文件 : " + param3;
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_ONE_RECORDER_FILE_FINISHED:
publisher_event = "已生成一个录像文件 : " + param3;
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_SEND_DELAY:
publisher_event = "发送时延: " + param1 + " 帧数:" + param2;
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CAPTURE_IMAGE:
publisher_event = "快照: " + param1 + " 路径:" + param3;
if (param1 == 0) {
publisher_event = publisher_event + "截取快照成功..";
} else {
publisher_event = publisher_event + "截取快照失败..";
}
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_RTSP_URL:
publisher_event = "RTSP服务URL: " + param3;
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUSH_RTSP_SERVER_RESPONSE_STATUS_CODE:
publisher_event = "RTSP status code received, codeID: " + param1 + ", RTSP URL: " + param3;
break;
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUSH_RTSP_SERVER_NOT_SUPPORT:
publisher_event = "服务器不支持RTSP推送, 推送的RTSP URL: " + param3;
break;
}
String str = "当前状态:" + publisher_event;
Log.i(TAG, str);
if (handler_ != null) {
Message message = new Message();
message.what = PUBLISHER_EVENT_MSG;
message.obj = publisher_event;
handler_.sendMessage(message);
}
}
});
6. 采集到的数据可以按需录像吗
可以,而且很有必要,智慧教室无纸化场景同屏的时候,如果需要把授课、开会等内容实时保存下来,这时候,可以随时启动录像。
public boolean startRecorder()
{
Log.i(TAG, "onClick startRecorder..");
if(!stream_publisher_.is_publishing())
{
startCaptureScreen();
}
if (layer_post_thread_ != null)
layer_post_thread_.update_layers();
if (stream_publisher_.is_recording()) {
stopRecorder();
return false;
}
InitAndSetConfig();
ConfigRecorderParam();
boolean start_ret = stream_publisher_.StartRecorder();
if (!start_ret) {
stream_publisher_.try_release();
Log.e(TAG, "Failed to start recorder.");
return false;
}
startAudioRecorder();
startLayerPostThread();
return true;
}
//停止录像
public void stopRecorder() {
stream_publisher_.StopRecorder();
stream_publisher_.try_release();
if (!stream_publisher_.is_publishing())
stopAudioRecorder();
}
7. 文字、图片水印
需要而且建议支持,比如实时时间、学校或公司logo等,需要叠加到屏幕数据的文字或者图片信息。
//水印效果选择++++++++++
watermarkSelctor = (Spinner) findViewById(R.id.watermarkSelctor);
watermarkSelctor.setEnabled(false);
final String[] watermarks = new String[]{"图片水印", "全部水印", "文字水印", "不加水印"};
ArrayAdapter<String> adapterWatermark = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, watermarks);
adapterWatermark.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
watermarkSelctor.setAdapter(adapterWatermark);
watermarkSelctor.setSelection(3,true);
watemarkType = 3; //默认不加水印
watermarkSelctor.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
watemarkType = position;
Log.i(TAG, "[水印类型]Currently choosing: " + watermarks[position] + ", watemarkType: " + watemarkType);
if(backgroudService !=null) {
backgroudService.updateWatermarker(watemarkType);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
8. 可以同时启动轻量级RTSP服务吗?
智慧教室场景下,如果需要对学生的屏幕进行轮循,或查看某个学生的屏幕,可以在学生端,启动轻量级的RTSP服务,然后,教师或管理终端,直接进行拉流就好。
public boolean startRtspService(int port)
{
Log.i(TAG, "startRtspService++");
rtsp_handle_ = lib_publisher_.OpenRtspServer(0);
if (rtsp_handle_ == 0) {
Log.e(TAG, "创建rtsp server实例失败! 请检查SDK有效性");
} else {
if (lib_publisher_.SetRtspServerPort(rtsp_handle_, port) != 0) {
lib_publisher_.CloseRtspServer(rtsp_handle_);
rtsp_handle_ = 0;
Log.e(TAG, "创建rtsp server端口失败! 请检查端口是否重复或者端口不在范围内!");
}
if (lib_publisher_.StartRtspServer(rtsp_handle_, 0) == 0) {
Log.i(TAG, "启动rtsp server 成功!");
} else {
lib_publisher_.CloseRtspServer(rtsp_handle_);
rtsp_handle_ = 0;
Log.e(TAG, "启动rtsp server失败! 请检查设置的端口是否被占用!");
}
isRTSPServiceRunning = true;
}
return true;
}
//停止RTSP服务
public void stopRtspService() {
Log.i(TAG, "stopRtspService++");
if(!isRTSPServiceRunning)
{
return;
}
if (lib_publisher_ != null && rtsp_handle_ != 0) {
lib_publisher_.StopRtspServer(rtsp_handle_);
lib_publisher_.CloseRtspServer(rtsp_handle_);
rtsp_handle_ = 0;
}
isRTSPServiceRunning = false;
}
public boolean startRtspPublisher(){
Log.i(TAG, "startRtspPublisher++");
if(!stream_publisher_.is_publishing())
{
startCaptureScreen();
}
InitAndSetConfig();
String rtsp_stream_name = "stream1";
stream_publisher_.SetRtspStreamName(rtsp_stream_name);
stream_publisher_.ClearRtspStreamServer();
stream_publisher_.AddRtspStreamServer(rtsp_handle_);
if (!stream_publisher_.StartRtspStream()) {
stream_publisher_.try_release();
Log.e(TAG, "调用发布rtsp流接口失败!");
return false;
}
startAudioRecorder();
startLayerPostThread();
return true;
}
//停止发布RTSP流
public void stopRtspPublisher() {
Log.i(TAG, "stopRtspPublisher++");
stream_publisher_.StopRtspStream();
stream_publisher_.try_release();
if (!stream_publisher_.is_publishing())
stopAudioRecorder();
}
public int getRtspSessionNumbers(){
int session_numbers = 0;
if (lib_publisher_ != null && rtsp_handle_ != 0) {
session_numbers = lib_publisher_.GetRtspServerClientSessionNumbers(rtsp_handle_);
Log.i(TAG, "GetRtspSessionNumbers: " + session_numbers);
}
return session_numbers;
}
9. 同屏延迟,能不能做到毫秒级
内网环境下,如果网络(比如无线AP)和设备性能没有瓶颈的前提下,使用大牛直播SDK的同屏和播放模块,可以轻松做到毫秒级延迟。下图以Android平台采集屏幕数据为例,分别推送RTMP服务和启动轻量级RTSP服务,windows端分别进行rtmp和rtsp拉流播放,整体时延。
10. 能不能采集到扬声器的audio?
Windows不在话下,Android平台需要高版本支持,高版本是可以采集到扬声器数据的,我们也实现了相关的demo,可以同时采集麦克风和扬声器的audio,单独推送或者同时混音输出。
11. 同屏过程中,重点画面可以快照吗?
当然可以,我们同屏采集端,支持采集编码png或jpg格式输出。
总结
智慧教室无纸化方案在教育、企业培训、科研机构和公共服务等多个领域都得到了广泛应用,并发挥了重要作用。随着技术的不断进步和应用场景的不断拓展,其应用前景将更加广阔。其实一个好的智慧教室无纸化同屏系统,需要考虑组网、分辨率、码率、时延、音视频同步和连续性等各个指标,本文抛砖引玉,感兴趣的开发者,可以跟我单独沟通讨论。