LiveKit的agent介绍
概念
LiveKit核心概念:
- Room(房间)
- Participant(参会人)
- Track(信息流追踪)
Agent 架构图
订阅信息流
agent交互流程
客户端操作
加入房间
房间创建方式
手动
赋予用户创建房间的权限,在客户的加入并创建房间。
自动
客户的指定ws_url和token,加入指定房间。
room = LiveKit.create(appContext = applicationContext)
room.connect(wsUrl, token)
离开房间
调用 Room.disconnect()
通知 LiveKit 离开事件。如果应用程序在未通知 LiveKit 的情况下关闭,则将继续显示参与者在 Room 中 15 秒。
Swift上,当应用程序退出时,会自动调用 Room.disconnect
。
发送消息
发送方式
客户端通过LocalParticipant.publishData
API 向房间中的任何参与者发布任意数据消息。房间数据通过 WebRTC 数据通道发布到SFU;LiveKit 服务器会将该数据转发给聊天室中的一个或多个参与者。
给指定用户发消息,通过设置destinationIdentities
,它表示用户的身份。
// 发送消息
coroutineScope.launch {val data: ByteArray = //...// 发送有损消息给全员,LOSSY表示数据发送一次,无顺序保证。这对于优先考虑交付速度的实时更新来说是理想的选择。room.localParticipant.publishData(data, DataPublishReliability.LOSSY)// 发送可靠的消息给指定成员,RELIABLE表示发送数据时最多重试3次并保证顺序。适合优先保证交付而不是抵延迟的场景,例如室内聊天。val identities = listOf(Participant.Identity("alice"),Participant.Identity("bob"),)room.localParticipant.publishData(data, DataPublishReliability.RELIABLE, identities)
}// 处理接收到的消息
coroutineScope.launch {room.events.collect { event ->if(event is RoomEvent.DataReceived) {// Process data}}
}
消息大小限制
由于 SCTP 协议的限制,对大于 16 KiB 的消息使用数据通道是不切实际的,包括 LiveKit 的协议包装器。我们建议将消息大小保持在 15 KiB 以下。详细了解数据通道大小限制。
消息的topic
消息可以指定topic,在接收方通过topic进行过滤出感兴趣的消息。
发送信息流
livekit默认支持摄像头、麦克风、录屏3个流,也支持用户发布自定义流的配置。
音视频流
// Turns camera track on
room.localParticipant.setCameraEnabled(true)// Turns microphone track on
room.localParticipant.setMicrophoneEnabled(true)
录屏流
// Create an intent launcher for screen capture
// This *must* be registered prior to onCreate(), ideally as an instance val
val screenCaptureIntentLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()
) { result ->val resultCode = result.resultCodeval data = result.dataif (resultCode != Activity.RESULT_OK || data == null) {return@registerForActivityResult}lifecycleScope.launch {room.localParticipant.setScreenShareEnabled(true, data)}
}// When it's time to enable the screen share, perform the following
val mediaProjectionManager =getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
screenCaptureIntentLauncher.launch(mediaProjectionManager.createScreenCaptureIntent())
自定义流配置
// Option 1: set room defaults
val options = RoomOptions(audioTrackCaptureDefaults = LocalAudioTrackOptions(noiseSuppression = true,echoCancellation = true,autoGainControl = true,highPassFilter = true,typingNoiseDetection = true,),videoTrackCaptureDefaults = LocalVideoTrackOptions(deviceId = "",position = CameraPosition.FRONT,captureParams = VideoPreset169.H1080.capture,),audioTrackPublishDefaults = AudioTrackPublishDefaults(audioBitrate = 20_000,dtx = true,),videoTrackPublishDefaults = VideoTrackPublishDefaults(videoEncoding = VideoPreset169.H1080.encoding,)
)
var room = LiveKit.create(...roomOptions = options,
)// Option 2: create tracks manually
val localParticipant = room.localParticipant
val audioTrack = localParticipant.createAudioTrack("audio")
localParticipant.publishAudioTrack(audioTrack)val videoTrack = localParticipant.createVideoTrack("video", LocalVideoTrackOptions(CameraPosition.FRONT,VideoPreset169.H1080.capture
))
localParticipant.publishVideoTrack(videoTrack)
订阅信息流
默认用户进入房间,会监听所有信息流。
coroutineScope.launch {room.events.collect { event ->when(event) {is RoomEvent.TrackSubscribed -> {// Audio tracks are automatically played.val videoTrack = event.track as? VideoTrack ?: return@collectvideoTrack.addRenderer(videoRenderer)}else -> {}}}
}
监听事件
事件分为:room事件和参与者事件。这是事件列表:
EVENT | DESCRIPTION | ROOM EVENT | PARTICIPANT EVENT |
ParticipantConnected 参与者Connected | A RemoteParticipant joins after the local participant. | ✔️ | |
RemoteParticipant 在本地参与者之后加入。 | |||
ParticipantDisconnected 参与者断开连接 | A RemoteParticipant leaves | ✔️ | |
RemoteParticipant 离开 | |||
Reconnecting 重新连接 | The connection to the server has been interrupted and it's attempting to reconnect. | ✔️ | |
与服务器的连接已中断,它正在尝试重新连接。 | |||
Reconnected 重新 | Reconnection has been successful | ✔️ | |
重新连接成功 | |||
Disconnected 断开 | Disconnected from room due to the room closing or unrecoverable failure | ✔️ | |
由于会议室关闭或无法恢复的故障而与会议室断开连接 | |||
TrackPublished 轨迹已发布 | A new track is published to room after the local participant has joined | ✔️ | ✔️ |
本地参加者加入后,新轨道将发布到聊天室 | |||
TrackUnpublished TrackUnpublished (未发布) | A RemoteParticipant has unpublished a track | ✔️ | ✔️ |
RemoteParticipant 已取消发布轨道 | |||
TrackSubscribed | The LocalParticipant has subscribed to a track | ✔️ | ✔️ |
LocalParticipant 已订阅跟踪 | |||
TrackUnsubscribed 跟踪Unsubscribed | A previously subscribed track has been unsubscribed | ✔️ | ✔️ |
之前订阅的曲目已取消订阅 | |||
TrackMuted TrackMuted (轨道静音) | A track was muted, fires for both local tracks and remote tracks | ✔️ | ✔️ |
轨道已静音,本地轨道和远程轨道均触发 | |||
TrackUnmuted TrackUnmuted (轨道未静音) | A track was unmuted, fires for both local tracks and remote tracks | ✔️ | ✔️ |
轨道已取消静音,本地轨道和远程轨道均触发 | |||
LocalTrackPublished LocalTrack已发布 | A local track was published successfully | ✔️ | ✔️ |
已成功发布本地轨道 | |||
LocalTrackUnpublished | A local track was unpublished | ✔️ | ✔️ |
本地曲目未发布 | |||
ActiveSpeakersChanged ActiveSpeakers已更改 | Current active speakers has changed | ✔️ | |
当前当前活跃的发言人已更改 | |||
IsSpeakingChanged | The current participant has changed speaking status | ✔️ | |
当前参与者已更改发言状态 | |||
ConnectionQualityChanged 连接质量已更改 | Connection quality was changed for a Participant | ✔️ | ✔️ |
参与者的连接质量已更改 | |||
ParticipantMetadataChanged | A participant's metadata was updated via server API | ✔️ | ✔️ |
参与者的元数据已通过服务器 API 更新 | |||
RoomMetadataChanged RoomMetadataChanged 的 | Metadata associated with the room has changed | ✔️ | |
与聊天室关联的元数据已更改 | |||
DataReceived 已接收数据 | Data received from another participant or server | ✔️ | ✔️ |
从其他参与者或服务器接收的数据 | |||
TrackStreamStateChanged TrackStreamStateChanged (已更改) | Indicates if a subscribed track has been paused due to bandwidth | ✔️ | ✔️ |
指示订阅的曲目是否因带宽而暂停 | |||
TrackSubscriptionPermissionChanged | One of subscribed tracks have changed track-level permissions for the current participant | ✔️ | ✔️ |
其中一个已订阅的轨道已更改当前参与者的轨道级别权限 | |||
ParticipantPermissionsChanged | When the current participant's permissions have changed | ✔️ | ✔️ |
ParticipantPermissions已更改 | 当前参与者的权限发生更改时 |
服务端操作
生成用户token
需要LiveKit服务的API_KEY和API-SECRET,通过LiveKit API生成JWT令牌。
通过登录JWT获取到用户的信息,identify=user_id+场景,name=用户昵称(默认值),room名称=场景名(user_id)
# server.py
import os
from livekit import api
from flask import Flaskapp = Flask(__name__)@app.route('/getToken')
def getToken():token = api.AccessToken(os.getenv('LIVEKIT_API_KEY'), os.getenv('LIVEKIT_API_SECRET')) \.with_identity("identity") \.with_name("my name") \.with_grants(api.VideoGrants(room_join=True,room="my-room",))return token.to_jwt()
开发环境可以通过CLI快速创建token:
livekit-cli token create --api-key devkey --api-secret secret --join --room test_room --identity test_user --valid-for 24h
token属性
基于JWT的令牌,包含用户身份、放假名称、功能、权限等。按照场景颁发token,也就是对应的房间。
聊天室权限在解码的加入令牌的 video
字段中指定。它可能包含以下一个或多个属性:
FIELD | TYPE | DESCRIPTION |
roomCreate room创建 | bool | Permission to create or delete rooms |
创建或删除聊天室的权限 | ||
roomList roomList 会议室 | bool | Permission to list available rooms |
列出可用会议室的权限 | ||
roomJoin room加入 | bool | Permission to join a room |
加入聊天室的权限 | ||
roomAdmin roomAdmin 管理员 | bool | Permission to moderate a room |
管理聊天室的权限 | ||
roomRecord roomRecord (房间记录) | bool | Permissions to use Egress service |
使用 Egress 服务的权限 | ||
ingressAdmin 入口管理员 | bool 布尔 | Permissions to use Ingress service |
Ingress 服务使用权限 | ||
room 房间 | string 字符串 | Name of the room, required if join or admin is set |
聊天室的名称,如果设置了 join 或 admin,则为必填项 | ||
canPublish 可以发布 | bool 布尔 | Allow participant to publish tracks |
允许参与者发布轨迹 | ||
canPublishData | bool 布尔 | Allow participant to publish data to the room |
允许参与者将数据发布到聊天室 | ||
canPublishSources | string[] 字符串[] | When set, only listed source can be published. (camera, microphone, screen_share, screen_share_audio) |
设置后,只能发布列出的源。(摄像头、麦克风、screen_share、screen_share_audio) | ||
canSubscribe canSubscribe 订阅 | bool 布尔 | Allow participant to subscribe to tracks |
允许参加者订阅曲目 | ||
canUpdateOwnMetadata | bool 布尔 | Allow participant to update its own metadata |
允许参与者更新自己的元数据 | ||
hidden 隐藏 | bool 布尔 | Hide participant from others in the room |
对聊天室中的其他人隐藏参与者 | ||
kind 类 | string 字符串 | Type of participant (standard, ingress, egress, sip, or agent). this field is typically set by LiveKit internals. |
参与者类型(标准、入口、出口、SIP 或代理)。此字段通常由 LiveKit 内部设置。 |
session断开操作
用户离开房间后,回话会结束,通过add_shutdown_callback回调,可以处理后续操作。例如:发送聊天结束事件。
async def entrypoint(ctx: JobContext):async def my_shutdown_hook():# save user state...ctx.add_shutdown_callback(my_shutdown_hook)
Agent操作
创建Agent服务节点
LiveKit的Agent框架现在只支持python的SDK,文档地址如下:https://docs.livekit.io/agents/quickstart/
这是官方给的demo:
import asynciofrom livekit.agents import AutoSubscribe, JobContext, WorkerOptions, cli, llm
from livekit.agents.voice_assistant import VoiceAssistant
from livekit.plugins import deepgram, openai, silero# This function is the entrypoint for the agent.
async def entrypoint(ctx: JobContext):# Create an initial chat context with a system promptinitial_ctx = llm.ChatContext().append(role="system",text=("You are a voice assistant created by LiveKit. Your interface with users will be voice. ""You should use short and concise responses, and avoiding usage of unpronouncable punctuation."),)# Connect to the LiveKit room# indicating that the agent will only subscribe to audio tracksawait ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)# VoiceAssistant is a class that creates a full conversational AI agent.# See https://github.com/livekit/agents/tree/main/livekit-agents/livekit/agents/voice_assistant# for details on how it works.assistant = VoiceAssistant(vad=silero.VAD.load(),stt=deepgram.STT(),llm=openai.LLM(),tts=openai.TTS(),chat_ctx=initial_ctx,)# Start the voice assistant with the LiveKit roomassistant.start(ctx.room)await asyncio.sleep(1)# Greets the user with an initial messageawait assistant.say("Hey, how can I help you today?", allow_interruptions=True)if __name__ == "__main__":# Initialize the worker with the entrypointcli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))
Agent的生命周期
- 当worker程序启动时,会通过websocket连接到LiveKit服务器,将自己注册成worker。一个worker下会有多个子进程(Agent)来处理请求。
- 当用户进入房间时,LiveKit服务器通过负载均衡选择一个worker,为用户提供服务。
- 子进程处理来自用户的消息,并给出回复。
- 当用户退出房间时,房间滚啊比,并且断开与agent的连接。
Agent内部执行流程
agent在处理请求时,包含几个节点:
- request handler:判断能否处理请求,不能请求则LiveKit会讲任务交给其他worker
- entrypoint:agent进入房间之前,执行的初始化操作
- prewarm function:agent进程启动时调用,可以执行加载模型等耗时的操作
Worker类型
opts = WorkerOptions(...# when omitted, the default is JobType.JT_ROOMworker_type=JobType.JT_ROOM,
)
JobType 枚举有两个选项:
- JT_ROOM:将为每个房间创建一个新的代理实例。
- JT_PUBLISHER:将为房间里的每个参与者创建一个新的代理实例。
Agent处理请求
处理音频流
@ctx.room.on("track_subscribed")
def on_track_subscribed(track: rtc.Track,publication: rtc.TrackPublication,participant: rtc.RemoteParticipant,
):# 监听音频流if track.kind == rtc.TrackKind.KIND_AUDIO:audio_stream = rtc.AudioStream(track)async for event in audio_stream:do_something(event.frame)
发布音频流
发布音频涉及将流拆分为长度固定的音频帧。内部缓冲区保存 50 毫秒长的音频队列,实时发送。用于发送新帧的 capture_frame 方法是阻塞的,在缓冲区接收整个帧之前阻塞在那里。这样可以更轻松地处理中断。
为了发布音轨,需要事先确定采样率和声道数,以及每帧的长度(样本数)。下面的示例是在 10ms 长帧中以 48kHz 传输恒定的 16 位正弦波:
SAMPLE_RATE = 48000
NUM_CHANNELS = 1 # mono audio
AMPLITUDE = 2 ** 8 - 1
SAMPLES_PER_CHANNEL = 480 # 10ms at 48kHzasync def entrypoint(ctx: JobContext):await ctx.connect()source = rtc.AudioSource(SAMPLE_RATE, NUM_CHANNELS)track = rtc.LocalAudioTrack.create_audio_track("example-track", source)# since the agent is a participant, our audio I/O is its "microphone"options = rtc.TrackPublishOptions(source=rtc.TrackSource.SOURCE_MICROPHONE)# ctx.agent is an alias for ctx.room.local_participantpublication = await ctx.agent.publish_track(track, options)frequency = 440async def _sinewave():audio_frame = rtc.AudioFrame.create(SAMPLE_RATE, NUM_CHANNELS, SAMPLES_PER_CHANNEL)audio_data = np.frombuffer(audio_frame.data, dtype=np.int16)time = np.arange(SAMPLES_PER_CHANNEL) / SAMPLE_RATEtotal_samples = 0while True:time = (total_samples + np.arange(SAMPLES_PER_CHANNEL)) / SAMPLE_RATEsinewave = (AMPLITUDE * np.sin(2 * np.pi * frequency * time)).astype(np.int16)np.copyto(audio_data, sinewave)# send this frame to the trackawait source.capture_frame(frame)total_samples += samples_per_channel
处理文本消息
监听data_received事件,处理用户发来的消息;通过publish_data()发送消息给用户。
@room.on("data_received")
def on_data_received(data: rtc.DataPacket):logging.info("received data from %s: %s", data.participant.identity, data.data)# string payload will be encoded to bytes with UTF-8
await room.local_participant.publish_data("my payload",reliable=True,destination_identities=["identity1", "identity2"],topic="topic1")
相关文章:

LiveKit的agent介绍
概念 LiveKit核心概念: Room(房间)Participant(参会人)Track(信息流追踪) Agent 架构图 订阅信息流 agent交互流程 客户端操作 加入房间 房间创建方式 手动 赋予用户创建房间的…...

青龙面板 升级 及其 依赖更新修复 检测and日志删除等
青龙版本升级 先关闭服务 cd qinglong目录 docker-compose down 关闭 docker pull whyour/qinglong:版本号 //版本号自行选择,如果是为了修复错误,建议版本微升,不然就直接latest 启动 docker-compose up -d 进入容器࿰…...

坐牢第三十七天(Qt)
作业: 使用qt做一个闹钟 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPixmap> #include <QBitmap> #include <QLabel> //标签类 #include <QLineEdit> //行编辑器类 #include <QPushBu…...

Vidu 全球首发「主体参照」新功能,一键同步角色特征;GPT-4o 实时音频项目负责人离职创业丨 RTE 开发者日报
开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…...

电子地图的主要功能与应用
电子地图,即数字地图,是利用计算机技术,以数字方式存储和查阅的地图。它不仅继承了传统纸质地图的基本功能,还通过现代科技手段实现了诸多创新应用。以下是电子地图的主要功能与应用: 一、主要功能 快速存取与显示&…...

基于Java+SpringBoot+Vue+MySQL的西安旅游管理系统网站
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的西安旅游管理系统网站【附源码文档】、…...

简单介绍 NVIDIA推出的图形处理单元(GPU)架构“安培架构“
概念 "安培架构"(Ampere Architecture)是 NVIDIA 推出的一款图形处理单元(GPU)架构,它是继图灵架构之后的下一代产品。安培架构最初在2020年发布,以其高性能和高效率而闻名,广泛应用…...

Qiskit:量子计算的Python工具包
Qiskit是由IBM开发的开源量子计算软件开发工具包,它提供了一套完整的工具,用于量子电路的设计、模拟、优化和执行。Qiskit支持量子算法的开发,并且可以与IBM的量子计算机硬件进行交互。 Qiskit的主要特点 量子电路设计:Qiskit允…...

Python——贪吃蛇
以下是一个简单的贪吃蛇游戏的Python代码示例: import pygame import time import random# 初始化 Pygame pygame.init()# 定义颜色 BLACK (0, 0, 0) WHITE (255, 255, 255) RED (255, 0, 0) GREEN (0, 255, 0) BLUE (0, 0, 255)# 设置屏幕尺寸 screen_width …...

WPF 依赖属性与附加属性(面试长问)
在WPF中,**依赖属性(Dependency Property)和附加属性(Attached Property)**是WPF依赖属性系统的重要组成部分。它们虽然都基于依赖属性系统,但用途、定义方式和使用场景有显著差异。以下是两者的详细解释及…...

Python 中的各括号用法
括号的使用 在Python中,括号和中括号有不同的用途: 圆括号 (): 函数调用:当你调用一个函数时,需要使用圆括号,即使没有参数。print("Hello, World!") # 调用print函数表达式分组:在…...

业务流程建模(BPM)的重要性及其应用
什么是业务流程建模(BPM)? 业务流程建模(BPM)是对企业内各项业务流程进行图形化描述的一种方法。它旨在通过可视化的方式帮助企业理解和分析现有的业务流程,从而发现潜在的问题并进行改进。BPM通常采用流程…...

isxdigit函数讲解 <ctype.h>头文件函数
目录 1.头文件 2.isxdigit函数使用 方源一把抓住VS2022,顷刻 炼化! 1.头文件 以上函数都需要包括头文件<ctype.h> ,其中包括 isxdigit 函数 #include<ctype.h> 2.isxdigit函数使用 isxdigit 函数是判断字符是否为十六进制数…...

Linux中安装NextCloud
切换为 root 账号 Ubutu 系统默认登录的用户为非 root 权限用户,为了能正常安装 nextCloud,需要切换为 root 账号。执行如下命令即可: sudo su 更新及安装基础包 请依次运行如下命令,有遇到询问的Is this ok [y/d/N]的时候直接键…...

【编程基础知识】什么是数据库事务
事务(Transaction)是数据库管理系统中的一个基本概念,用于确保数据库操作的原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability…...

移植案例与原理 - XTS子系统之应用兼容性测试用例开发
往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 startup子系统之syspara_lite系统属性部件 (1) startup子系统之syspara_lite系统属性部件 (2) startup子系…...

关于linux里的df命令以及inode、数据块-stat链接数以及关于awk文本处理命令中内置函数sub、gsub、sprintf
一、关于linux里的df命令以及inode、数据块-stat链接数 Linux中df命令用于显示目前在Linux系统上的文件系统的磁盘使用情况统计,平常这个命令也用得很多,但一般就是使用df -h查看各个分区的空间使用情况,除此外也可以使用df查看当前linux系统…...

如何本地搭建Whisper语音识别模型
要在本地搭建Whisper语音识别模型,您需要以下几个步骤: 步骤一:系统准备 操作系统: 建议使用Ubuntu 20.04或以上版本,确保系统足够稳定和兼容。硬件配置: 最好有一个强大的GPU,因为语音识别涉及大量的计算工作。推荐…...

微信小程序仿微信聊天界面
界面结构: 消息列表: 使用 scroll-view 实现滚动,每条消息使用 view 组件包裹,根据消息类型 (文本、图片、文件) 显示不同内容。输入框区域: 包含输入框 (textarea)、发送按钮 (button) 和上传文件按钮 (view 组件模拟)。头像: 使用 image 组件展示。 …...

文件用电脑生成的在线技巧,能够轻松将多种类型文件转二维码
现在为了能够更加快捷将文件分享给其他人查看,很多人会通过制作二维码的方式来存储文件,这样可以减少文件对内存的占用,而且用户扫码获取内容也更加的方便快捷。二维码能够随时更新内容,可以长期通过一个二维码来提供个不同的内容…...

QT实现TCP/UDP通信
服务器端: 客户端: 服务器: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QTcpSocket> #include <QList> #include <QMessageBox> #include <QDebug&…...

流程自动化变革:看低代码开发如何赋能企业创新转型
在数字化转型的浪潮中,企业面临着前所未有的挑战和机遇。为了保持竞争力,企业必须快速适应市场变化,创新业务模式,并提高运营效率。流程自动化成为企业转型的关键,而低代码开发平台如JNPF,正成为推动这一变…...

可提示 3D 分割研究里程碑!SAM2Point:SAM2加持泛化任意3D场景、任意提示!
郑重声明:本解读已获得论文作者的原创解读授权 文章链接:https://arxiv.org/pdf/2408.16768 在线demo: https://huggingface.co/spaces/ZiyuG/SAM2Point code链接:https://github.com/ZiyuGuo99/SAM2Point 亮点直击 无投影 3D 分割࿱…...

Rabbitmq中得RPC调用代码详解
文章目录 1.RPC客户端2.RabbitMQ连接信息实体类3.XML工具类 本文档只是为了留档方便以后工作运维,或者给同事分享文档内容比较简陋命令也不是特别全,不适合小白观看,如有不懂可以私信,上班期间都是在得 直接上代码了 1.RPC客户端 …...

ISAC: Toward Dual-Functional Wireless Networks for 6G and Beyond【论文阅读笔记】
此系列是本人阅读论文过程中的简单笔记,比较随意且具有严重的偏向性(偏向自己研究方向和感兴趣的),随缘分享,共同进步~ Integrated Sensing and Communications: Toward Dual-Functional Wireless Networks for 6G and…...

split 分割字符串方法解析,substring 截取字符串方法解析;二者的作用和区别?使用时需要注意什么?附代码和运行图
目录 一. 摘要 二. split 方法 2.1 String[] split(String regix) 2.2 String[] split(String regix,int limit) 2.3.1 当 int < 0时,会按照最大数量切割字符串 2.3.2 当 int 0时,此时就和第一个方法一样了,等于没有传入…...

HTTP 协议的基本格式
HTTP协议("超文本传输协议"),是一个被广泛使用应用层协议,自1991年正式发布HTTP协议以来,HTTP协议就一直在更新,目前已经更新到3.0版本,但是目前主流的依旧是1.1版本,但依旧是一个最主流使用的应…...

STM32-HAL库开发快速入门
注:本文主要记录一下STM32CubeMX软件的使用流程,记录内容以STM32外设(中断、I2C、USART、SPI等配置)在STM32CubeMX中的设置为主,对驱动代码编写不做记录,所以阅读本文最好有标准库开发经验。除第2节外,使用的都是韦东山…...

vue3-print打印eletable某一行的数据
主页面的表格 <template><el-table :data"list"><el-table-column label"操作" align"center"><template #default"scope"><el-buttonlinktype"primary"click"handleType(scope.row)"…...

【Vue】pnpm创建Vue3+Vite项目
初始化项目 (1)cmd切换到指定工作目录,运行pnpm create vue命令,输入项目名称后按需安装组件 (2)使用vs code打开所创建的项目目录,Ctrl~快捷键打开终端,输入pnpm install下载项目…...