从零实现Electron屏幕共享:基于WebRTC的跨平台解决方案
2026-02-05 04:01:22作者:余洋婵Anita
你是否在开发Electron应用时遇到屏幕共享难题?WebRTC API调用复杂?跨平台兼容性差?安全权限处理繁琐?本文将基于gh_mirrors/el/electron-quick-start项目,提供一套完整的屏幕共享实现方案,从基础架构到高级优化,助你快速掌握这一关键技术。
读完本文你将获得:
- 3种屏幕捕获模式的完整实现代码
- 主进程与渲染进程通信的安全配置
- 跨平台兼容性处理的最佳实践
- 10个性能优化技巧与常见问题解决方案
一、Electron屏幕共享技术架构
Electron结合Chromium的WebRTC能力与Node.js的系统访问权限,为屏幕共享提供了独特优势。理解其技术架构是实现高质量共享的基础。
1.1 核心技术栈
mindmap
root((Electron屏幕共享))
WebRTC API
getUserMedia
MediaStream
RTCPeerConnection
Electron API
desktopCapturer
ipcMain/ipcRenderer
contextBridge
通信架构
主进程
渲染进程
进程间通信
跨平台适配
Windows
macOS
Linux
1.2 进程间通信模型
Electron的多进程架构要求屏幕共享功能在主进程与渲染进程间协同工作:
sequenceDiagram
participant 渲染进程 as Renderer Process
participant Preload as Preload Script
participant 主进程 as Main Process
participant OS as 操作系统
渲染进程->>Preload: 请求屏幕捕获
Preload->>主进程: 发送捕获请求(ipc)
主进程->>OS: 调用系统屏幕捕获API
OS-->>主进程: 返回屏幕/窗口列表
主进程-->>Preload: 传递媒体流信息
Preload-->>渲染进程: 提供MediaStream
渲染进程->>渲染进程: 显示共享内容/WebRTC传输
1.3 三种捕获模式对比
| 捕获模式 | 实现难度 | 适用场景 | 性能消耗 | 跨平台支持 |
|---|---|---|---|---|
| 整个屏幕 | ★☆☆☆☆ | 全屏演示 | 中 | Windows/macOS/Linux |
| 应用窗口 | ★★☆☆☆ | 应用演示 | 低 | Windows/macOS |
| 自定义区域 | ★★★☆☆ | 精确区域共享 | 高 | 全平台 |
二、基础屏幕捕获实现
2.1 配置Preload脚本(安全通信层)
首先修改preload.js,建立主进程与渲染进程的安全通信通道:
const { contextBridge, ipcRenderer } = require('electron');
// 暴露屏幕共享API到渲染进程
contextBridge.exposeInMainWorld('screenShareAPI', {
getSources: () => ipcRenderer.invoke('screen-share:get-sources'),
startCapture: (sourceId) => ipcRenderer.invoke('screen-share:start-capture', sourceId),
stopCapture: () => ipcRenderer.invoke('screen-share:stop-capture')
});
// 原有代码保持不变
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
});
2.2 实现主进程捕获逻辑
修改main.js,添加屏幕捕获相关的主进程代码:
const { app, BrowserWindow, ipcMain, desktopCapturer } = require('electron');
const path = require('node:path');
let mainWindow;
let mediaStream = null;
// 获取可用的屏幕/窗口源
ipcMain.handle('screen-share:get-sources', async () => {
try {
const sources = await desktopCapturer.getSources({
types: ['window', 'screen'],
thumbnailSize: { width: 1280, height: 720 }
});
return sources.map(source => ({
id: source.id,
name: source.name,
thumbnailURL: source.thumbnail.toDataURL(),
displayId: source.displayId
}));
} catch (error) {
console.error('获取捕获源失败:', error);
throw error;
}
});
// 开始屏幕捕获
ipcMain.handle('screen-share:start-capture', async (event, sourceId) => {
try {
// 停止已有捕获
if (mediaStream) {
mediaStream.getTracks().forEach(track => track.stop());
}
// 获取媒体流
mediaStream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sourceId,
minWidth: 1280,
maxWidth: 1920,
minHeight: 720,
maxHeight: 1080
}
}
});
// 返回流ID供渲染进程使用
return mediaStream.id;
} catch (error) {
console.error('开始捕获失败:', error);
throw error;
}
});
// 停止屏幕捕获
ipcMain.handle('screen-share:stop-capture', async () => {
if (mediaStream) {
mediaStream.getTracks().forEach(track => track.stop());
mediaStream = null;
}
return true;
});
// 保持原有的createWindow函数和窗口配置
function createWindow () {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
// 启用必要的功能
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false
}
});
mainWindow.loadFile('index.html');
}
// ... 保持其他原有代码不变
2.3 修改HTML页面(添加UI元素)
更新index.html,添加屏幕共享所需的UI组件:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src self; script-src self; style-src self unsafe-inline">
<link href="./styles.css" rel="stylesheet">
<title>Electron屏幕共享演示</title>
</head>
<body>
<h1>Electron WebRTC屏幕共享</h1>
<!-- 屏幕共享控制区 -->
<div class="share-controls">
<button id="selectSourceBtn">选择共享源</button>
<button id="startShareBtn" disabled>开始共享</button>
<button id="stopShareBtn" disabled>停止共享</button>
</div>
<!-- 共享源选择列表 -->
<div id="sourceList" class="source-list"></div>
<!-- 共享预览区 -->
<div class="preview-container">
<h3>共享预览</h3>
<video id="sharePreview" autoplay muted class="preview-video"></video>
</div>
<script src="./renderer.js"></script>
</body>
</html>
2.4 添加样式表(styles.css)
/* 共享控制区样式 */
.share-controls {
margin: 20px 0;
display: flex;
gap: 10px;
}
button {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
#startShareBtn {
background-color: #4CAF50;
color: white;
}
#stopShareBtn {
background-color: #f44336;
color: white;
}
#selectSourceBtn {
background-color: #2196F3;
color: white;
}
/* 共享源列表样式 */
.source-list {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin: 20px 0;
max-height: 200px;
overflow-y: auto;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.source-item {
width: 200px;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
cursor: pointer;
transition: all 0.2s;
}
.source-item.selected {
border-color: #2196F3;
background-color: #e3f2fd;
}
.source-item img {
width: 100%;
height: 120px;
object-fit: cover;
}
.source-item p {
margin: 10px 0 0;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* 预览区样式 */
.preview-container {
margin-top: 20px;
}
.preview-video {
width: 100%;
max-width: 800px;
border: 1px solid #ccc;
border-radius: 4px;
}
2.5 实现渲染进程逻辑(renderer.js)
document.addEventListener('DOMContentLoaded', () => {
// DOM元素
const selectSourceBtn = document.getElementById('selectSourceBtn');
const startShareBtn = document.getElementById('startShareBtn');
const stopShareBtn = document.getElementById('stopShareBtn');
const sourceList = document.getElementById('sourceList');
const sharePreview = document.getElementById('sharePreview');
// 状态变量
let selectedSourceId = null;
let mediaStream = null;
// 选择共享源
selectSourceBtn.addEventListener('click', async () => {
try {
// 从主进程获取可用的共享源
const sources = await window.screenShareAPI.getSources();
// 清空列表并添加新源
sourceList.innerHTML = '';
sources.forEach(source => {
const sourceItem = document.createElement('div');
sourceItem.className = 'source-item';
sourceItem.innerHTML = `
<img src="${source.thumbnailURL}" alt="${source.name}">
<p>${source.name}</p>
`;
// 点击选择源
sourceItem.addEventListener('click', () => {
// 移除其他项的选中状态
document.querySelectorAll('.source-item').forEach(item =>
item.classList.remove('selected'));
// 添加当前项选中状态
sourceItem.classList.add('selected');
selectedSourceId = source.id;
startShareBtn.disabled = false;
});
sourceList.appendChild(sourceItem);
});
} catch (error) {
console.error('获取共享源失败:', error);
alert(`获取共享源失败: ${error.message}`);
}
});
// 开始共享
startShareBtn.addEventListener('click', async () => {
if (!selectedSourceId) return;
try {
// 开始捕获并获取媒体流
const streamId = await window.screenShareAPI.startCapture(selectedSourceId);
// 获取媒体流(实际项目中可能需要通过WebRTC传输到其他端)
// 这里简化处理,直接显示在本地预览
mediaStream = new MediaStream();
// 在实际应用中,这里应该通过RTCPeerConnection发送流
// 这里为简化演示,直接使用一个模拟的流播放
// 注意:真实场景下需要通过WebRTC建立对等连接
sharePreview.srcObject = mediaStream;
// 更新UI状态
startShareBtn.disabled = true;
stopShareBtn.disabled = false;
selectSourceBtn.disabled = true;
} catch (error) {
console.error('开始共享失败:', error);
alert(`开始共享失败: ${error.message}`);
}
});
// 停止共享
stopShareBtn.addEventListener('click', async () => {
try {
await window.screenShareAPI.stopCapture();
// 清除预览
if (sharePreview.srcObject) {
sharePreview.srcObject.getTracks().forEach(track => track.stop());
sharePreview.srcObject = null;
}
// 重置状态
selectedSourceId = null;
startShareBtn.disabled = true;
stopShareBtn.disabled = true;
selectSourceBtn.disabled = false;
sourceList.innerHTML = '';
} catch (error) {
console.error('停止共享失败:', error);
alert(`停止共享失败: ${error.message}`);
}
});
// 窗口关闭时停止共享
window.addEventListener('beforeunload', () => {
if (mediaStream) {
window.screenShareAPI.stopCapture();
}
});
// 原有图表初始化代码保持不变
initChart();
});
// 保持原有的initChart函数不变
const Chart = require('chart.js/auto');
function initChart() {
// ... (原有代码保持不变)
}
三、WebRTC对等连接实现
3.1 WebRTC连接架构
flowchart TD
A[本地Electron应用] -->|1. 创建offer| B[信令服务器]
B -->|2. 转发offer| C[远程对等端]
C -->|3. 创建answer| B
B -->|4. 转发answer| A
A -->|5. 交换ICE候选| B
B -->|6. 转发ICE候选| C
A <-->|7. P2P媒体流| C
3.2 添加WebRTC连接代码(renderer.js补充)
// 在renderer.js中添加WebRTC相关功能
let peerConnection;
const configuration = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' }
]
};
// 创建P2P连接
async function createPeerConnection(isInitiator) {
// 创建RTCPeerConnection实例
peerConnection = new RTCPeerConnection(configuration);
// 添加ICE候选处理
peerConnection.onicecandidate = (event) => {
if (event.candidate) {
// 发送ICE候选到信令服务器
sendSignalingMessage({
type: 'candidate',
candidate: event.candidate
});
}
};
// 处理远程流
peerConnection.ontrack = (event) => {
// 这里可以处理接收到的远程流
console.log('Received remote stream');
// remoteVideo.srcObject = event.streams[0];
};
// 如果是发起方,创建offer
if (isInitiator && mediaStream) {
// 添加本地流到连接
mediaStream.getTracks().forEach(track => {
peerConnection.addTrack(track, mediaStream);
});
try {
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
// 发送offer到信令服务器
sendSignalingMessage({
type: 'offer',
sdp: peerConnection.localDescription
});
} catch (error) {
console.error('创建offer失败:', error);
}
}
}
// 信令消息处理(实际项目中需要连接到信令服务器)
function handleSignalingMessage(message) {
if (!peerConnection) {
// 如果不是发起方,创建连接并设置远程描述
createPeerConnection(false);
}
switch (message.type) {
case 'offer':
peerConnection.setRemoteDescription(new RTCSessionDescription(message.sdp))
.then(() => {
if (mediaStream) {
mediaStream.getTracks().forEach(track => {
peerConnection.addTrack(track, mediaStream);
});
}
return peerConnection.createAnswer();
})
.then(answer => {
return peerConnection.setLocalDescription(answer);
})
.then(() => {
sendSignalingMessage({
type: 'answer',
sdp: peerConnection.localDescription
});
})
.catch(error => {
console.error('处理offer失败:', error);
});
break;
case 'answer':
peerConnection.setRemoteDescription(new RTCSessionDescription(message.sdp))
.catch(error => console.error('处理answer失败:', error));
break;
case 'candidate':
if (message.candidate) {
peerConnection.addIceCandidate(new RTCIceCandidate(message.candidate))
.catch(error => console.error('添加ICE候选失败:', error));
}
break;
}
}
// 发送信令消息(实际项目中需要实现与信令服务器的通信)
function sendSignalingMessage(message) {
// 这里简化处理,实际项目中应该通过WebSocket等方式发送到信令服务器
console.log('发送信令消息:', message);
// 在实际应用中,这里需要连接到信令服务器
// 例如使用WebSocket:
// ws.send(JSON.stringify(message));
}
// 在开始共享后添加WebRTC连接初始化
// 修改startShareBtn的click事件处理:
// ... 原有代码 ...
// 开始捕获并获取媒体流
const streamId = await window.screenShareAPI.startCapture(selectedSourceId);
// 获取媒体流
mediaStream = new MediaStream();
// 初始化WebRTC连接(作为发起方)
createPeerConnection(true);
// ... 原有代码 ...
四、跨平台兼容性处理
4.1 平台特定代码处理
不同操作系统对屏幕捕获有不同的权限要求和API行为,需要针对性处理:
// 在main.js中修改getSources处理函数
ipcMain.handle('screen-share:get-sources', async (event, options) => {
try {
// 平台特定配置
const captureOptions = {
types: ['window', 'screen'],
thumbnailSize: {
width: 1280,
height: 720
}
};
// macOS特定配置
if (process.platform === 'darwin') {
captureOptions.fetchWindowIcons = true;
}
// Windows特定配置
if (process.platform === 'win32') {
captureOptions.thumbnailSize.width = 1920;
captureOptions.thumbnailSize.height = 1080;
}
const sources = await desktopCapturer.getSources(captureOptions);
return sources.map(source => ({
id: source.id,
name: source.name,
thumbnailURL: source.thumbnail.toDataURL(),
displayId: source.displayId,
// 平台特定信息
isScreen: source.name.includes('Screen'),
isWindow: source.name.includes('Window')
}));
} catch (error) {
console.error('获取捕获源失败:', error);
throw error;
}
});
4.2 权限请求处理
macOS和Linux需要额外的权限处理:
// 在main.js中添加权限检查
function checkPermissions() {
return new Promise((resolve, reject) => {
// macOS权限检查
if (process.platform === 'darwin') {
const { systemPreferences } = require('electron');
// 检查屏幕录制权限
if (!systemPreferences.getMediaAccessStatus('screen')) {
systemPreferences.askForMediaAccess('screen')
.then(granted => {
if (granted) resolve(true);
else reject(new Error('需要屏幕录制权限,请在系统偏好设置中启用'));
});
} else {
resolve(true);
}
}
// Linux不需要额外权限
else if (process.platform === 'linux') {
resolve(true);
}
// Windows权限由系统自动处理
else if (process.platform === 'win32') {
resolve(true);
}
});
}
// 在创建窗口前检查权限
app.whenReady().then(async () => {
try {
// 检查权限
await checkPermissions();
// 创建窗口
createWindow();
// ... 其他初始化代码
} catch (error) {
console.error('权限检查失败:', error);
// 显示权限错误对话框
dialog.showErrorBox(
'权限不足',
error.message + '\n请在系统设置中启用必要的权限后重试。'
);
app.quit();
}
});
4.3 跨平台问题解决方案
| 问题 | 平台 | 解决方案 | 代码示例 |
|---|---|---|---|
| 窗口标题乱码 | Windows | 使用win32 API获取窗口标题 | const { nativeImage } = require('electron') |
| 捕获黑屏 | macOS | 检查辅助功能权限 | systemPreferences.getMediaAccessStatus('screen') |
| 性能低下 | Linux | 降低捕获分辨率 | thumbnailSize: { width: 1280, height: 720 } |
| 窗口闪烁 | Windows | 禁用硬件加速 | app.disableHardwareAcceleration() |
五、性能优化与最佳实践
5.1 捕获参数优化
// 在main.js中优化捕获参数
ipcMain.handle('screen-share:start-capture', async (event, sourceId) => {
try {
// 停止已有捕获
if (mediaStream) {
mediaStream.getTracks().forEach(track => track.stop());
}
// 动态调整捕获参数
const captureParams = {
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sourceId,
// 动态分辨率设置
minWidth: 1280,
maxWidth: 1920,
minHeight: 720,
maxHeight: 1080,
// 帧率控制
minFrameRate: 15,
maxFrameRate: 30
}
}
};
// 根据源类型调整参数(窗口/屏幕)
if (sourceId.includes('window')) {
// 窗口捕获降低分辨率
captureParams.video.mandatory.maxWidth = 1280;
captureParams.video.mandatory.maxHeight = 720;
}
// 低性能设备检测
const isLowPerformance = process.getSystemMemoryInfo().total < 4 * 1024 * 1024 * 1024; // <4GB内存
if (isLowPerformance) {
captureParams.video.mandatory.maxFrameRate = 15;
captureParams.video.mandatory.maxWidth = 1024;
captureParams.video.mandatory.maxHeight = 768;
}
mediaStream = await navigator.mediaDevices.getUserMedia(captureParams);
return mediaStream.id;
} catch (error) {
console.error('开始捕获失败:', error);
throw error;
}
});
5.2 常见问题与解决方案
问题1:捕获帧率低,画面卡顿
解决方案:
- 降低捕获分辨率
- 限制最大帧率
- 禁用不必要的渲染效果
// 在renderer.js中添加帧率控制
function setVideoQuality(qualityLevel) {
// 0: 低质量, 1: 中等, 2: 高质量
const qualitySettings = [
{ width: 800, height: 600, frameRate: 15 },
{ width: 1280, height: 720, frameRate: 24 },
{ width: 1920, height: 1080, frameRate: 30 }
];
const settings = qualitySettings[qualityLevel];
// 通知主进程更改捕获参数
window.screenShareAPI.setCaptureParams(settings)
.then(() => console.log('视频质量已更新'))
.catch(error => console.error('更新视频质量失败:', error));
}
问题2:远程端延迟高
解决方案:
- 优化WebRTC配置
- 使用低延迟编解码器
- 调整JitterBuffer大小
// 优化WebRTC配置
const configuration = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
// 添加turn服务器改善连接
{
urls: 'turn:your-turn-server.com:3478',
username: 'username',
credential: 'credential'
}
],
// 启用低延迟模式
iceCandidatePoolSize: 10,
sdpSemantics: 'unified-plan'
};
// 创建PeerConnection时添加参数
const peerConnection = new RTCPeerConnection({
...configuration,
// 媒体优化参数
bundlePolicy: 'max-bundle',
rtcpMuxPolicy: 'require',
// 低延迟配置
latencyHint: 'interactive' // 交互模式,低延迟优先
});
// 设置编解码器偏好
peerConnection.addTransceiver('video', { direction: 'sendrecv' });
peerConnection.addTransceiver('audio', { direction: 'sendrecv' });
// 在创建offer时指定编解码器
const offerOptions = {
offerToReceiveVideo: true,
offerToReceiveAudio: true,
voiceActivityDetection: false,
// 优先使用VP8编解码器
codecPreferences: ['video/VP8', 'audio/opus']
};
问题3:应用占用CPU过高
解决方案:
- 实现按需捕获
- 非活跃时降低帧率
- 使用硬件编码
// 在renderer.js中实现按需捕获
let isActive = true;
// 监听页面可见性变化
document.addEventListener('visibilitychange', () => {
isActive = !document.hidden;
adjustCaptureFrameRate(isActive ? 30 : 5); // 活跃时30fps,非活跃时5fps
});
// 调整捕获帧率
async function adjustCaptureFrameRate(frameRate) {
if (!mediaStream) return;
const videoTrack = mediaStream.getVideoTracks()[0];
if (!videoTrack) return;
try {
// 调整视频轨道约束
await videoTrack.applyConstraints({
frameRate: { ideal: frameRate, max: frameRate }
});
console.log(`帧率已调整为: ${frameRate}fps`);
} catch (error) {
console.error('调整帧率失败:', error);
}
}
六、项目集成与部署
6.1 项目文件结构
electron-quick-start/
├── index.html # 添加共享UI
├── main.js # 添加屏幕捕获主进程代码
├── preload.js # 添加安全通信层
├── renderer.js # 添加共享控制逻辑
├── styles.css # 添加共享相关样式
├── package.json # 添加依赖
└── assets/
└── icons/ # 添加托盘和窗口图标
6.2 依赖安装
项目需要添加WebRTC相关依赖:
npm install webrtc-adapter --save
npm install socket.io-client --save # 如果使用Socket.IO作为信令通道
在package.json中添加:
"dependencies": {
"webrtc-adapter": "^8.2.3",
"socket.io-client": "^4.5.1",
// ... 其他依赖
}
6.3 打包配置
修改package.json,添加打包脚本:
"scripts": {
"start": "electron .",
"package": "electron-packager . --overwrite --platform=all --icon=assets/icons/icon --out=dist",
"package:win": "electron-packager . --overwrite --platform=win32 --icon=assets/icons/icon.ico --out=dist",
"package:mac": "electron-packager . --overwrite --platform=darwin --icon=assets/icons/icon.icns --out=dist",
"package:linux": "electron-packager . --overwrite --platform=linux --icon=assets/icons/icon.png --out=dist"
}
6.4 安全最佳实践
- 权限控制:仅在需要时请求屏幕捕获权限
- 验证源ID:确保只处理可信的源ID
- 加密传输:使用HTTPS和安全的WebRTC连接
- 输入验证:验证所有IPC消息
- 最小权限原则:限制渲染进程权限
// 在preload.js中添加消息验证
contextBridge.exposeInMainWorld('screenShareAPI', {
getSources: () => {
// 记录请求
console.log('getSources requested at', new Date().toISOString());
return ipcRenderer.invoke('screen-share:get-sources');
},
startCapture: (sourceId) => {
// 验证sourceId格式
if (typeof sourceId !== 'string' || !sourceId.startsWith('window') && !sourceId.startsWith('screen')) {
console.error('Invalid sourceId:', sourceId);
throw new Error('Invalid source ID');
}
return ipcRenderer.invoke('screen-share:start-capture', sourceId);
},
stopCapture: () => ipcRenderer.invoke('screen-share:stop-capture')
});
七、总结与扩展
本文基于gh_mirrors/el/electron-quick-start项目,实现了一套完整的Electron屏幕共享方案,包括:
- 基于WebRTC和Electron desktopCapturer的屏幕捕获实现
- 安全的进程间通信架构设计
- 跨平台兼容性处理
- 性能优化与常见问题解决方案
- WebRTC实时传输集成
7.1 功能扩展方向
- 多显示器支持:检测并允许选择特定显示器
- 音频共享:添加系统音频捕获功能
- 鼠标指针捕获:显示远程鼠标指针
- 权限持久化:记住用户的权限选择
- 录制功能:将共享内容保存为视频文件
7.2 学习资源推荐
- Electron官方文档 - desktopCapturer
- WebRTC官方文档
- MDN - MediaStream API
- SimpleWebRTC - 简化WebRTC开发的库
- Electron屏幕共享示例项目
如果觉得本文有帮助,请点赞👍收藏🌟关注,下一篇将带来《Electron+WebRTC实现视频会议系统》。
附录:完整代码清单
登录后查看全文
热门项目推荐
相关项目推荐
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00- QQwen3-Coder-Next2026年2月4日,正式发布的Qwen3-Coder-Next,一款专为编码智能体和本地开发场景设计的开源语言模型。Python00
xw-cli实现国产算力大模型零门槛部署,一键跑通 Qwen、GLM-4.7、Minimax-2.1、DeepSeek-OCR 等模型Go06
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin08
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00
项目优选
收起
deepin linux kernel
C
27
11
OpenHarmony documentation | OpenHarmony开发者文档
Dockerfile
532
3.74 K
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
336
177
Ascend Extension for PyTorch
Python
340
404
React Native鸿蒙化仓库
JavaScript
302
355
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
886
596
暂无简介
Dart
770
191
华为昇腾面向大规模分布式训练的多模态大模型套件,支撑多模态生成、多模态理解。
Python
114
140
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
12
1
openJiuwen agent-studio提供零码、低码可视化开发和工作流编排,模型、知识库、插件等各资源管理能力
TSX
986
247