当前位置: 首页 > news >正文

如何设计开发RTSP直播播放器?

技术背景

我们在对接RTSP直播播放器相关技术诉求的时候,好多开发者,除了选用成熟的RTSP播放器外,还想知其然知其所以然,对RTSP播放器的整体开发有个基础的了解,方便方案之作和技术延伸。本文抛砖引玉,做个大概的介绍。

技术实现

技术难点

在探讨RTSP直播播放器技术实现之前,我们先来看,为什么RTSP播放器的开发看似简单,实则复杂,或者说做播放器容易,做个好的播放器,为什么就那么难?

协议复杂性
  1. 理解 RTSP 协议规范
    • RTSP 协议本身比较复杂,包含多种请求方法(如 OPTIONS、DESCRIBE、SETUP、PLAY、PAUSE、TEARDOWN 等)、状态码和头部字段。开发者需要深入理解这些规范,以便正确地与服务器进行交互。
    • 例如,在处理 DESCRIBE 请求时,需要解析服务器返回的媒体描述信息,其中可能包含复杂的 SDP(Session Description Protocol)格式,包括媒体类型、编码方式、帧率、分辨率等参数的描述。理解和解析这些信息需要对协议规范有深入的了解。
  2. 处理不同的协议变种和扩展
    • 在实际应用中,可能会遇到不同的 RTSP 服务器实现,它们可能会有一些协议变种或自定义的扩展。开发者需要能够处理这些差异,确保播放器能够与各种服务器兼容。
    • 例如,某些服务器可能会在 RTSP 响应中添加自定义的头部字段,或者对标准的请求方法有不同的处理方式。开发者需要能够识别这些差异,并进行相应的处理,以保证播放器的兼容性。
网络环境的不确定性
  1. 适应不同的网络条件
    • RTSP 播放器需要在各种网络环境下工作,包括不同的带宽、延迟、丢包率等。开发者需要考虑如何适应这些不同的网络条件,以确保视频的流畅播放。
    • 例如,在低带宽环境下,可能需要采用自适应比特率技术,根据网络状况动态调整视频的码率,以避免卡顿和缓冲。在高延迟网络中,需要优化播放控制算法,减少播放延迟,提高用户体验。
  2. 处理网络错误和异常情况
    • 网络环境中可能会出现各种错误和异常情况,如连接中断、服务器故障、丢包等。开发者需要能够处理这些情况,进行适当的错误恢复和重试机制,以保证播放器的稳定性。
    • 例如,当连接中断时,播放器需要能够自动尝试重新连接服务器,并在重新连接成功后继续播放。当出现丢包情况时,需要采用适当的错误隐藏技术,如帧间插值或重复上一帧,以减少视频的卡顿和花屏现象。
视频解码和播放的复杂性
  1. 支持多种视频编码格式
    • RTSP 流可以使用多种视频编码格式,如 H.264、H.265、MPEG-4 等。开发者需要选择合适的视频解码器,并确保播放器能够支持各种常见的编码格式。
    • 不同的编码格式具有不同的特点和复杂性,需要对其进行深入了解和处理。例如,H.265 编码具有更高的压缩率,但解码复杂度也更高。开发者需要选择高效的解码器,并进行优化,以确保在不同设备上的性能表现。
  2. 处理视频同步问题
    • 在播放视频时,需要确保音频和视频的同步播放。这涉及到处理视频和音频的时间戳、帧率、采样率等参数,以及进行适当的同步调整。
    • 视频和音频的同步是一个复杂的问题,需要考虑多种因素,如网络延迟、解码时间、播放设备的性能等。开发者需要采用适当的同步算法,确保音频和视频的同步播放,提高用户体验。
跨平台开发的挑战
  1. 适应不同的操作系统和设备
    • RTSP 播放器需要在不同的操作系统和设备上运行,如 Windows、Linux、Android、iOS 等。开发者需要考虑如何进行跨平台开发,确保播放器在各种平台上都能正常工作。
    • 不同的平台具有不同的开发环境、编程语言和多媒体框架,需要进行相应的适配和优化。例如,在 Android 平台上,可能需要使用 Java 或 Kotlin 进行开发,并利用 Android 的多媒体框架;在 iOS 平台上,可能需要使用 Objective-C 或 Swift 进行开发,并利用 iOS 的 AVFoundation 框架。
  2. 处理不同的硬件特性
    • 不同的设备具有不同的硬件特性,如处理器性能、内存大小、图形处理能力等。开发者需要考虑如何优化播放器的性能,以适应不同设备的硬件特性。
    • 例如,在性能较低的设备上,可能需要采用更高效的解码算法和播放控制策略,以减少资源占用和提高播放流畅性。在具有硬件加速功能的设备上,可以利用硬件加速来提高解码和播放性能。

技术选型

编程语言和平台
  • 选择适合的编程语言和开发平台。常见的选择包括 C++、Java、Python等编程语言,以及 Android、iOS、Windows、Linux 等操作系统平台。
  • 例如,在 Android平台上可以使用 Java 或 Kotlin 进行开发,利用 Android SDK 提供的多媒体框架和网络功能来实现 RTSP 播放器。,也可以通过jni接口封装,核心业务在底层,对上提供jni调用接口。
多媒体框架和库
  • 选择合适的多媒体框架和库来实现视频解码和播放功能。一些常用的多媒体框架和库包括 FFmpeg、GStreamer、VLC 等。
  • 这些框架和库提供了丰富的功能,如视频解码、音频解码、流媒体协议支持等,可以大大简化 RTSP 播放器的开发过程。例如,FFmpeg 是一个广泛使用的开源多媒体框架,支持众多的视频和音频格式以及流媒体协议,可以在多个平台上使用。
了解RTSP协议
  1. 协议结构和工作原理
    • 深入了解 RTSP 协议的结构和工作原理。RTSP 是一个应用层协议,用于控制实时流媒体的传输。它使用 TCP 或 UDP 作为传输层协议,通过发送请求和接收响应来实现对媒体流的控制。
    • RTSP 协议的主要功能包括媒体流的播放、暂停、快进、快退等操作,以及媒体流的描述、设置和传输控制等。了解 RTSP 协议的请求和响应格式、状态码、方法等内容,对于开发 RTSP 播放器至关重要。
  2. 协议交互过程
    • 熟悉 RTSP 协议的交互过程。当播放器连接到 RTSP 服务器时,首先发送 OPTIONS 请求以获取服务器支持的方法列表。然后,播放器发送 DESCRIBE 请求获取媒体流的描述信息,包括媒体格式、编码方式、帧率等。
    • 根据媒体流的描述信息,播放器选择合适的解码器进行视频和音频解码。接下来,播放器发送 SETUP 请求建立媒体流的传输连接,并发送 PLAY 请求开始播放媒体流。在播放过程中,播放器可以发送 PAUSE、TEARDOWN 等请求来控制媒体流的播放状态。

实现播放器功能

网络连接和数据接收
  • 实现与 RTSP 服务器的网络连接和数据接收功能。使用所选编程语言的网络编程库,建立与 RTSP 服务器的 TCP 或 UDP 连接,并接收服务器发送的媒体流数据。
  • 在接收数据时,需要处理网络错误、丢包等情况,确保数据的完整性和准确性。可以使用缓冲区来存储接收到的数据,以便后续的解码和播放操作。
视频解码和播放
  • 选择合适的视频解码器对接收的媒体流数据进行解码,并将解码后的视频帧显示在屏幕上。根据所选的多媒体框架和库,配置解码器参数,如视频格式、分辨率、帧率等。
  • 对于视频播放,可以使用图形库或多媒体框架提供的显示功能,将解码后的视频帧绘制在窗口或视图中。同时,需要处理视频的同步问题,确保音频和视频的同步播放。
音频解码和播放
  • 对接收的媒体流数据中的音频部分进行解码,并通过音频设备播放出来。选择合适的音频解码器,配置解码器参数,如音频格式、采样率、声道数等。
  • 使用音频输出库或多媒体框架提供的音频播放功能,将解码后的音频数据发送到音频设备进行播放。同样,需要处理音频的同步问题,确保音频和视频的同步播放。
播放控制和用户界面
  • 实现播放控制功能,如播放、暂停、快进、快退等操作。通过发送相应的 RTSP 请求来控制媒体流的播放状态,并在用户界面上提供相应的控制按钮。
  • 设计用户界面,包括视频显示区域、播放控制按钮、进度条等。使用图形用户界面库或开发平台提供的界面设计工具,创建直观、易用的用户界面。

SmartPlayer设计实现

以大牛直播SDK的SmartPlayer RTSP直播播放模块为例,我们来看看,如何实现低延迟的RTSP播放器。大牛直播SDK自2015年发布RTSP、RTMP直播播放模块,迭代从未停止,SmartPlayer功能强大、性能强劲、高稳定、超低延迟、超低资源占用。无需赘述,全自研内核,行业内一致认可的跨平台RTSP、RTMP直播播放器。先说功能设计,如不单独说明,Windows、Linux(x86_64|aarch64架构)、Android、iOS全平台支持。

  •  [多实例播放]支持多实例播放;
  •  [事件回调]支持网络状态、buffer状态等回调;
  •  [视频格式]支持H.265、H.264,此外,还支持RTSP MJPEG播放;
  •  [音频格式]支持AAC/PCMA/PCMU;
  •  [H.264/H.265软解码]支持H.264/H.265软解;
  •  [H.264硬解码]Windows/Android/iOS支持特定机型H.264硬解;
  •  [H.265硬解]Windows/Android/iOS支持特定机型H.265硬解;
  •  [H.264/H.265硬解码]Android支持设置Surface模式硬解和普通模式硬解码;
  •  [RTSP模式设置]支持RTSP TCP/UDP模式设置;
  •  [RTSP TCP/UDP自动切换]支持RTSP TCP、UDP模式自动切换;
  •  [RTSP超时设置]支持RTSP超时时间设置,单位:秒;
  •  [RTSP 401认证处理]支持上报RTSP 401事件,如URL携带鉴权信息,会自动处理;
  •  [缓冲时间设置]支持buffer time设置;
  •  [首屏秒开]支持首屏秒开模式;
  •  [复杂网络处理]支持断网重连等各种网络环境自动适配;
  •  [快速切换URL]支持播放过程中,快速切换其他URL,内容切换更快;
  •  [音视频多种render机制]Android平台,视频:surfaceview/OpenGL ES,音频:AudioTrack/OpenSL ES;
  •  [实时静音]支持播放过程中,实时静音/取消静音;
  •  [实时音量调节]支持播放过程中实时调节音量;
  •  [实时快照]支持播放过程中截取当前播放画面;
  •  [只播关键帧]Windows平台支持实时设置是否只播放关键帧;
  •  [渲染角度]支持0°,90°,180°和270°四个视频画面渲染角度设置;
  •  [渲染镜像]支持水平反转、垂直反转模式设置;
  •  [等比例缩放]支持图像等比例缩放绘制(Android设置surface模式硬解模式不支持);
  •  [实时下载速度更新]支持当前下载速度实时回调(支持设置回调时间间隔);
  •  [解码前视频数据回调]支持H.264/H.265数据回调;
  •  [解码后视频数据回调]支持解码后YUV/RGB数据回调;
  •  [解码前音频数据回调]支持AAC/PCMA/PCMU数据回调;
  •  [音视频自适应]支持播放过程中,音视频信息改变后自适应;
  •  [扩展录像功能]完美支持和录像SDK组合使用。
RTSP播放器设计要点

1. 低延迟:大多数RTSP的播放都面向直播场景,所以,如果延迟过大,严重影响体验,所以,低延迟是衡量一个好的RTSP播放器非常重要的指标,目前大牛直播SDK的RTSP直播播放延迟比开源播放器更优异,而且长时间运行下,不会造成延迟累积;

2. 音视频同步处理有些播放器为了追求低延迟,甚至不做音视频同步,拿到audio video直接播放,导致a/v不同步,还有就是时间戳乱跳等各种问题,大牛直播SDK提供的播放器,具备好的时间戳同步和异常时间戳矫正机制;

3. 支持多实例:大牛直播SDK提供的播放器支持同时播放多路音视频数据,比如4-8-9窗口,大多开源播放器对多实例支持不太友好;

4. 支持buffer time设置:在一些有网络抖动的场景,播放器需要支持buffer time设置,一般来说,以毫秒计,开源播放器对此支持不够友好;

5. TCP/UDP模式设定自动切换:考虑到好多服务器仅支持TCP或UDP模式,一个好的RTSP播放器需要支持TCP/UDP模式设置,如链接不支持TCP或UDP,大牛直播SDK可自动切换,,开源播放器不具备自动切换TCP/UDP能力;

6. 实时静音:比如,多窗口播放RTSP流,如果每个audio都播放出来,体验非常不好,所以实时静音功能非常必要,开源播放器不具备实时静音功能;

7. 视频view旋转:好多摄像头由于安装限制,导致图像倒置,所以一个好的RTSP播放器应该支持如视频view实时旋转(0° 90° 180° 270°)、水平反转、垂直反转,开源播放器不具备此功能;

8. 支持解码后audio/video数据输出:大牛直播SDK接触到好多开发者,希望能在播放的同时,获取到YUV或RGB数据,进行人脸匹配等算法分析,开源播放器不具备此功能;

9. 实时快照:感兴趣或重要的画面,实时截取下来非常必要,一般播放器不具备快照能力,开源播放器不具备此功能;

10. 网络抖动处理(如断网重连):稳定的网络处理机制、支持如断网重连等,开源播放器对网络异常处理支持较差;

11. 长期运行稳定性:不同于市面上的开源播放器,大牛直播SDK提供的Windows平台RTSP直播播放SDK适用于数天长时间运行,开源播放器对长时间运行稳定性支持较差;

12. log信息记录:整体流程机制记录到LOG文件,确保出问题时,有据可依,开源播放器几无log记录。

13. 实时下载速度反馈:大牛直播SDK提供音视频流实时下载回调,并可设置回调时间间隔,确保实时下载速度反馈,以此来监听网络状态,开源播放器不具备此能力;

14. 异常状态处理Event状态回调如播放的过程中,断网、网络抖动、等各种场景,大牛直播SDK提供的播放器可实时回调相关状态,确保上层模块感知处理,开源播放器对此支持不好;

15. 关键帧/全帧播放实时切换:特别是播放多路画面的时候,如果路数过多,全部解码、绘制,系统资源占用会加大,如果能灵活的处理,可以随时只播放关键帧,全帧播放切换,对系统性能要求大幅降低。

Android平台RTSP播放示例

下面以Android平台多实例RTSP播放为例,探讨下接口设计和调用说明。

我们针对的功能展示,主要是播放和录像这块,先说播放:

/** SmartPlayer.java* Author: https://daniusdk.com* WeChat: xinsheng120* Created by DaniuLive on 2015/09/26.*/
class ButtonPlayback1Listener implements View.OnClickListener {public void onClick(View v) {if (stream_player_1_.is_playing()) {Log.i(TAG, "Stop player1..");boolean iRet = stream_player_1_.StopPlayer();if (!iRet) {Log.e(TAG, "Call StopPlayer failed..");return;}stream_player_1_.try_release();btn_playback1.setText("开始播放1");SetViewVisibility(surface_view_1_);} else {Log.i(TAG, "Start playback stream1++");int play_buffer = 0;int is_using_tcp = 0;if(!stream_player_1_.OpenPlayerHandle(playback_url_1_, play_buffer, is_using_tcp))return;stream_player_1_.SetView(surface_view_1_);boolean is_mute = false;boolean iPlaybackRet = stream_player_1_.StartPlayer(isHardwareDecoder, is_enable_hardware_render_mode, is_mute);if (!iPlaybackRet) {Log.e(TAG, "Call StartPlayer failed..");return;}btn_playback1.setText("停止播放1");}}
}

对应的OpenPlayerHandle()实现如下:

/** LibPlayerWrapper.java.java* Author: https://daniusdk.com*/
public boolean OpenPlayerHandle(String playback_url, int play_buffer, int is_using_tcp) {if (check_native_handle())return true;if(!isValidRtspOrRtmpUrl(playback_url))return false;long handle = lib_player_.SmartPlayerOpen(application_context());if (0==handle) {Log.e(TAG, "sdk open failed!");return false;}lib_player_.SetSmartPlayerEventCallbackV2(handle, new EventHandleV2());lib_player_.SmartPlayerSetBuffer(handle, play_buffer);// set report download speed(默认2秒一次回调 用户可自行调整report间隔)lib_player_.SmartPlayerSetReportDownloadSpeed(handle, 1, 4);boolean isFastStartup = true;lib_player_.SmartPlayerSetFastStartup(handle, isFastStartup ? 1 : 0);//设置RTSP超时时间int rtsp_timeout = 10;lib_player_.SmartPlayerSetRTSPTimeout(handle, rtsp_timeout);//设置RTSP TCP/UDP模式自动切换int is_auto_switch_tcp_udp = 1;lib_player_.SmartPlayerSetRTSPAutoSwitchTcpUdp(handle, is_auto_switch_tcp_udp);lib_player_.SmartPlayerSaveImageFlag(handle, 1);// It only used when playback RTSP stream..lib_player_.SmartPlayerSetRTSPTcpMode(handle, is_using_tcp);lib_player_.DisableEnhancedRTMP(handle, 0);lib_player_.SmartPlayerSetUrl(handle, playback_url);set(handle);return true;
}

对应的开始播放、停止播放设计:

/** LibPlayerWrapper.java* Author: https://daniusdk.com*/
public boolean StartPlayer(boolean is_hardware_decoder, boolean is_enable_hardware_render_mode, boolean is_mute) {if (is_playing()) {Log.e(TAG, "already playing, native_handle:" + get());return false;}SetPlayerParam(is_hardware_decoder, is_enable_hardware_render_mode, is_mute);int ret = lib_player_.SmartPlayerStartPlay(get());if (ret != OK) {Log.e(TAG, "call StartPlay failed, native_handle:" + get() + ", ret:" + ret);return false;}write_lock_.lock();try {this.is_playing_ = true;} finally {write_lock_.unlock();}Log.i(TAG, "call StartPlayer OK, native_handle:" + get());return true;
}public boolean StopPlayer() {if (!check_native_handle())return false;if (!is_playing()) {Log.w(TAG, "it's not playing, native_handle:" + get());return false;}boolean is_need_call = false;write_lock_.lock();try {if (this.is_playing_) {this.is_playing_ = false;is_need_call = true;}} finally {write_lock_.unlock();}if (is_need_call)lib_player_.SmartPlayerStopPlay(get());return true;
}

录像设计:

/** SmartPlayer.java* Author: https://daniusdk.com*/
class ButtonRecorder1Listener implements View.OnClickListener {public void onClick(View v) {if (stream_player_1_.is_recording()) {Log.i(TAG, "Stop recorder1..");boolean iRet = stream_player_1_.StopRecorder();if (!iRet) {Log.e(TAG, "Call StopRecorder failed..");return;}stream_player_1_.try_release();btn_recorder1.setText("开始录像1");} else {Log.i(TAG, "Start recorder stream1++");int play_buffer = 0;int is_using_tcp = 0;if(!stream_player_1_.OpenPlayerHandle(playback_url_1_, play_buffer, is_using_tcp))return;stream_player_1_.ConfigRecorderParam(recDir, 400, 1, 1, 1);boolean iRecRet = stream_player_1_.StartRecorder();if (!iRecRet) {Log.e(TAG, "Call StartRecorder failed..");return;}btn_recorder1.setText("停止录像1");}}
}

录像参数配置选项:

/** LibPlayerWrapper.java* Author: https://daniusdk.com*/
public boolean ConfigRecorderParam(String rec_dir, int file_max_size, int is_transcode_aac,int is_record_video, int is_record_audio) {if(!check_native_handle())return false;if (null == rec_dir || rec_dir.isEmpty())return false;int ret = lib_player_.SmartPlayerCreateFileDirectory(rec_dir);if (ret != 0) {Log.e(TAG, "Create record dir failed, path:" + rec_dir);return false;}if (lib_player_.SmartPlayerSetRecorderDirectory(get(), rec_dir) != 0) {Log.e(TAG, "Set record dir failed , path:" + rec_dir);return false;}if (lib_player_.SmartPlayerSetRecorderFileMaxSize(get(),file_max_size) != 0) {Log.e(TAG, "SmartPlayerSetRecorderFileMaxSize failed.");return false;}lib_player_.SmartPlayerSetRecorderAudioTranscodeAAC(get(), is_transcode_aac);// 更细粒度控制录像的, 一般情况无需调用lib_player_.SmartPlayerSetRecorderVideo(get(), is_record_video);lib_player_.SmartPlayerSetRecorderAudio(get(), is_record_audio);return true;
}

开始录像、结束录像:

/** LibPlayerWrapper.java* Author: https://daniusdk.com*/
public boolean StartRecorder() {if (is_recording()) {Log.e(TAG, "already recording, native_handle:" + get());return false;}int ret = lib_player_.SmartPlayerStartRecorder(get());if (ret != OK) {Log.e(TAG, "call SmartPlayerStartRecorder failed, native_handle:" + get() + ", ret:" + ret);return false;}write_lock_.lock();try {this.is_recording_ = true;} finally {write_lock_.unlock();}Log.i(TAG, "call SmartPlayerStartRecorder OK, native_handle:" + get());return true;
}public boolean StopRecorder() {if (!check_native_handle())return false;if (!is_recording()) {Log.w(TAG, "it's not recording, native_handle:" + get());return false;}boolean is_need_call = false;write_lock_.lock();try {if (this.is_recording_) {this.is_recording_ = false;is_need_call = true;}} finally {write_lock_.unlock();}if (is_need_call)lib_player_.SmartPlayerStopRecorder(get());return true;
}

总结

做RTSP播放器容易,做个可以稳定用于实际场景的低延迟RTSP播放器,真的非常困难,首先,RTSP协议本身的复杂度,如果不涉及底层协议栈,只是开源的项目编译调试小修小改,遇到问题,很难处理。还有就是网络环境的不确定性,视频解码和播放的复杂性,视频同步问题的复杂性及考虑因素。最后在跨平台开发的挑战,不同操作系统和设备以及处理不同硬件特性,都需要考虑。以上抛砖引玉,感兴趣的开发者,可以单独跟我沟通探讨。

相关文章:

如何设计开发RTSP直播播放器?

技术背景 我们在对接RTSP直播播放器相关技术诉求的时候,好多开发者,除了选用成熟的RTSP播放器外,还想知其然知其所以然,对RTSP播放器的整体开发有个基础的了解,方便方案之作和技术延伸。本文抛砖引玉,做个…...

Java基础系列-一文搞懂自定义排序

java自定义排序 自定义排序的理解&#xff1a; 我们首先看需求&#xff1a;一个二维数组 [[1,3],[8,10],[15,18],[2,6]] 我们的需求是根据集合&#xff08;二维数组取出来的数据&#xff09; 左边小的左边这种方式排序 例如1<8 排序方式就是[1,3],[8,10] 此时我们就需…...

扫普通链接二维码打开小程序

1. 2.新增规则&#xff08;注意下载文件到跟目录下&#xff0c;需要建个文件夹放下载的校验文件&#xff09; 3.发布 ps&#xff1a;发布后&#xff0c;只能访问正式版本。体验版本如果加了 测试链接http://xxx/xsc/10 那么http://xxx/xsc/aa.....应该都能访问 例如aa101 aa…...

计算机储存与分区

Disk partitioning 盘分区是在辅助储存上创建一个或多个区域&#xff0c;以便可以单独管理每个区域。而这些区域称为分区&#xff08;partition&#xff09;。这通常是在为新盘选择分区方案后&#xff0c;需要做的事。 MBR and GPT 分区方案&#xff08;分区表&#xff09;有…...

OpenCV之换脸技术:一场面部识别的奇妙之旅

在这个数字化与智能化并进的时代&#xff0c;图像处理技术日益成为连接现实与虚拟世界的桥梁。其中&#xff0c;换脸技术作为一项颇受欢迎且富有挑战性的应用&#xff0c;不仅让人惊叹于技术的魔力&#xff0c;更在娱乐、影视制作等领域展现了无限可能。今天&#xff0c;我们就…...

Linux学习笔记9 文件系统的基础

一、查看文件组织结构 Linux中一切都是文件。 Linux和Win的文件系统不是一个结构&#xff0c;Linux存在的根目录是所有目录的起点。 所有的存储空间和设备共享一个根目录&#xff0c;不同的磁盘块和分区挂载在其下&#xff0c;成为某个子目录的子目录&#xff0c;甚至设备也挂…...

Android OpenGL粒子特效

在本篇&#xff0c;我们将开启一个新的项目&#xff0c;探索粒子的世界。粒子是一种基本的图形元素&#xff0c;它们通常被表示为一组点。通过巧妙地组合一些基础的物理效果&#xff0c;我们能够创造出许多令人惊叹的视觉效果。想象一下&#xff0c;我们可以模拟一个水滴从喷泉…...

5 -《本地部署开源大模型》在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战

在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战 无论是在单机单卡&#xff08;一台机器上只有一块GPU&#xff09;还是单机多卡&#xff08;一台机器上有多块GPU&#xff09;的硬件配置上启动ChatGLM3-6B模型&#xff0c;其前置环境配置和项目文件是相同的。如果大家对配置过程还…...

dpkg:错误:另外一个进程已经为dpkg前端锁加锁

一、 问题描述 在新装ubuntu系统时&#xff0c;我们常常会遇见dpkg的错误&#xff0c;dpkg:错误:另外一个进程已经为dpkg前端锁加锁&#xff0c;如下图。 二、问题解决 方法一 先执行sudo rm /var/lib/dpkg/lock-frontend然后再继续安装软件包&#xff0c;如果出现问题dpkg:…...

基于SSM服装定制系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;服装类型管理&#xff0c;服装信息管理&#xff0c;服装定制管理&#xff0c;留言反馈&#xff0c;系统管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xf…...

RK3588开发笔记-usb3.0 xhci-hcd控制器挂死问题解决

目录 前言 一、问题现象 二、问题分析 三、问题排查 总结 前言 在使用 RK3588 芯片进行开发的过程中,我遇到了 USB 3.0 xHCI-HCD 控制器外接5G通讯模块偶尔挂死的问题。这个问题导致 USB 设备失去响应,且不能恢复,需要重启整个系统才能恢复使用,针对该问题进行大量测试以…...

深入解析TCP/IP协议:网络通信的基石

1. 引言 TCP/IP 协议是现代计算机网络的核心&#xff0c;它为互联网上的设备提供了通信的基础。在网络通信中&#xff0c;TCP/IP 协议栈是无处不在的&#xff0c;无论是个人设备的浏览器请求&#xff0c;还是大型分布式系统的内部通信&#xff0c;都依赖于它的稳定、高效与可靠…...

基于微信小程序的汽车预约维修系统(lw+演示+源码+运行)

基于微信小程序的汽车预约维修系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的汽车预约维修系统的开发全过程。通过分析基于微信小程序的汽车预约维修系统管理的不足&#xff0c;创建了…...

wifi、热点密码破解 - python

乐子脚本&#xff0c;有点小慢&#xff0c;试过多线程&#xff0c;系统 wifi 连接太慢了&#xff0c;需要时间确认&#xff0c;多线程的话系统根本反应不过来。 也就可以试试破解别人的热点&#xff0c;一般都是 123456 这样的傻鸟口令 # coding:utf-8 import pywifi from pyw…...

bean的实例化2024年10月17日

跟不上为基础 1.你的java学习路线 2. 3.课程 注解的装配 contoller调用service用的是注解装配...

告别ELK,APO提供基于ClickHouse开箱即用的高效日志方案——APO 0.6.0发布

ELK一直是日志领域的主流产品&#xff0c;但是ElasticSearch的成本很高&#xff0c;查询效果随着数据量的增加越来越慢。业界已经有很多公司&#xff0c;比如滴滴、B站、Uber、Cloudflare都已经使用ClickHose作为ElasticSearch的替代品&#xff0c;都取得了不错的效果&#xff…...

Excel使用技巧:定位Ctrl+G +公式+原位填充 Ctrl+Enter快速填充数据(处理合并单元格)

Excel的正确用法&#xff1a; Excel是个数据库&#xff0c;不要随意合并单元格。 数据输入的时候一定要按照行列输入&#xff0c;中间不要留空&#xff0c;不然就没有关联。 定位CtrlG 公式原位填充 CtrlEnter快速填充数据 如果把合并的单元格 取消合并&#xff0c;只有第一…...

JAVA学习-练习试用Java实现“成绩归类”

问题&#xff1a; 编写程序&#xff0c;输入一批学生的成绩&#xff0c;遇0或负数则输入结束&#xff0c;要求统计并输出优秀&#xff08;大于85&#xff09;、通过&#xff08;60&#xff5e;84&#xff09;和不及格&#xff08;小于60&#xff09;的学生人数。 示例 &#x…...

【Hive】7-拉链表的设计与实现

拉链表的设计与实现 数据同步问题 背景 例如&#xff1a;MySQL中有一张用户表: tb_user&#xff0c;每个用户注册完成以后&#xff0c;就会在用户表中新增该用户的信息&#xff0c;记录该用户的id、手机号码、用户名、性别、地址等信息。 每天都会有用户注册&#xff0c;产生…...

Maxwell 底层原理 详解

Maxwell 是一个 MySQL 数据库的增量数据捕获&#xff08;CDC, Change Data Capture&#xff09;工具&#xff0c;它通过读取 MySQL 的 binlog&#xff08;Binary Log&#xff09;来捕获数据变化&#xff0c;并将这些变化实时地发送到如 Kafka、Kinesis、RabbitMQ 或其他输出端。…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...