news 2026/8/30 11:03:36

[无缝衔接自动化与手动测试]:Playwright MCP扩展连接现有浏览器会话指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[无缝衔接自动化与手动测试]:Playwright MCP扩展连接现有浏览器会话指南

[无缝衔接自动化与手动测试]:Playwright MCP扩展连接现有浏览器会话指南

【免费下载链接】playwright-mcpPlaywright Tools for MCP项目地址: https://gitcode.com/gh_mirrors/pl/playwright-mcp

问题导入:当自动化遇上手动操作的困境

在日常开发与测试工作中,我们经常面临这样的场景:需要对一个已登录的网页进行自动化测试,但重新构建登录状态需要复杂的验证码验证;或者在手动调试发现bug后,希望直接将当前页面状态交给自动化脚本进行复现和验证。传统方案要么需要编写大量代码模拟用户操作,要么无法保留手动操作的上下文状态,导致效率低下。

Playwright MCP(Multi-Context Protocol)扩展正是为解决这一痛点而生,它像一座桥梁,将已存在的浏览器会话与自动化脚本连接起来,让我们能够在保留现有页面状态的同时,享受自动化测试的便捷。

核心价值:重新定义浏览器自动化工作流

Playwright MCP扩展通过创新的会话共享技术,为开发者带来三大核心价值:

  • 状态复用:无需重复构建测试环境,直接使用已有的页面上下文(如登录状态、表单数据)
  • 混合操作:在自动化流程中插入手动操作,解决自动化难以处理的复杂场景
  • 实时协作:将本地浏览器会话共享给远程团队成员,便于问题诊断与协作调试

[!TIP] 想象一下,这就像你正在使用的电脑可以被远程操控,同时你还能看到并参与操作,既保留了当前的工作状态,又能让自动化工具协助完成重复性任务。

工作机制与环境准备

技术原理解析

Playwright MCP扩展基于Chrome扩展Manifest V3架构,通过WebSocket中继与CDP(Chrome DevTools Protocol)协议实现会话共享。简单来说,它在你的浏览器和自动化脚本之间建立了一条双向通信通道,让脚本能够像你自己操作一样控制浏览器,同时保留所有已有的页面状态。

核心工作流程包括三个阶段:

  1. 初始化阶段:自动化脚本启动MCP服务器并等待连接
  2. 权限验证阶段:扩展解析连接参数并请求用户授权
  3. 会话建立阶段:用户确认后,扩展激活调试接口并转发CDP事件

环境配置要求

环境版本要求备注
Chrome/Edge≥ 98.0必须支持Manifest V3扩展架构
Node.js≥ 18.0构建扩展与运行测试所需
Playwright≥ 1.30.0MCP协议支持基础

安装步骤

🔧目标:从源码构建并安装Playwright MCP扩展

# 克隆项目仓库 git clone https://gitcode.com/gh_mirrors/pl/playwright-mcp.git cd playwright-mcp # 安装项目依赖 npm install # 构建扩展 cd packages/extension npm run build

🔧目标:在Chrome浏览器中加载扩展

  1. 打开Chrome浏览器,访问chrome://extensions
  2. 启用右上角"开发者模式"开关
  3. 点击"加载已解压的扩展程序"按钮
  4. 选择刚刚构建的playwright-mcp/packages/extension/dist目录
  5. 验证扩展图标是否出现在浏览器工具栏中

[!TIP] 安装成功后,浏览器工具栏会出现Playwright MCP扩展图标,默认状态为灰色,表示未连接。

常见误区

❌ 错误:直接使用npm install安装扩展而不进行构建

✅ 正确:必须执行npm run build生成可加载的扩展文件

❌ 错误:尝试在不支持Manifest V3的旧版浏览器中安装

✅ 正确:确保Chrome/Edge版本≥98.0,可通过chrome://version查看版本信息

实践操作:连接现有会话的完整流程

启动MCP服务器

🔧目标:启动支持MCP协议的Playwright服务器

const { chromium } = require('playwright'); (async () => { // 启动支持MCP协议的浏览器实例 const browser = await chromium.launch({ args: [ '--mcp-server=ws://localhost:8080', // MCP服务器监听地址 '--mcp-allow-origin=*' // 允许的源地址,生产环境应限制具体域名 ] }); // 保持服务器运行以等待扩展连接 console.log('MCP服务器已启动,等待扩展连接...'); console.log('服务器地址: ws://localhost:8080'); })();

执行上述代码后,终端应显示"服务器地址: ws://localhost:8080",表示MCP服务器已成功启动。

发起连接请求

🔧目标:在自动化脚本中发起会话连接请求

// 调用MCP工具发起连接请求 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', // 连接类型 mcpRelayUrl: 'ws://localhost:8080', // MCP服务器地址 timeout: 30000 // 连接超时时间(毫秒) } }); // 验证连接结果 if (connectResponse.success) { console.log('连接请求已发送,等待用户授权'); console.log('会话ID:', connectResponse.sessionId); } else { console.error('连接请求失败:', connectResponse.error); }

执行后,浏览器会自动打开扩展的连接确认页面,等待用户交互。

授权并选择目标标签页

🔧目标:在扩展界面中完成连接授权

  1. 在弹出的扩展连接页面中,验证显示的服务器信息是否正确
  2. 从标签页列表中选择要共享的页面(列表显示所有当前打开的标签页标题)
  3. 点击"Connect"按钮完成授权

授权成功后,扩展图标将变为绿色,并显示"已连接"状态提示。

验证连接状态

🔧目标:确认会话已成功连接

// 检查连接状态 const status = await client.callTool({ name: 'get_connection_status', arguments: { sessionId: connectResponse.sessionId } }); if (status.isConnected) { console.log('会话已成功连接'); console.log('当前标签页:', status.tabInfo.title); console.log('连接时长:', status.duration); } else { console.log('会话未连接'); }

成功连接后,自动化脚本即可像控制普通Playwright页面一样控制已连接的标签页。

常见误区

❌ 错误:服务器地址使用http://协议而非ws://

✅ 正确:MCP服务器使用WebSocket协议,地址应以ws://wss://开头

❌ 错误:授权后立即关闭浏览器扩展的弹出窗口

✅ 正确:保持弹出窗口打开直到连接建立完成,连接成功后可最小化但不要关闭

基础配置:自定义连接参数与管理

配置连接超时设置

🔧目标:设置会话连接超时时间与自动断开机制

// 设置会话超时的示例代码 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: 'ws://localhost:8080', timeout: 30000, // 连接超时(30秒) sessionTimeout: 1800000 // 会话超时(30分钟) } });

此配置确保在指定时间内无操作时自动断开连接,提高安全性。

选择特定标签页连接

🔧目标:指定连接特定窗口和标签页

// 获取所有标签页信息 const tabs = await client.callTool({ name: 'list_tabs' }); // 筛选包含"登录"的标签页 const targetTab = tabs.find(tab => tab.title.includes('登录')); // 连接指定标签页 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: 'ws://localhost:8080', tabId: targetTab.id // 指定标签页ID } });

通过标签页ID或标题筛选,可以精确控制连接目标。

断开与重连机制

🔧目标:实现安全断开连接与自动重连

// 安全断开连接 await client.callTool({ name: 'browser_disconnect', arguments: { sessionId: connectResponse.sessionId, reason: '测试完成' // 记录断开原因 } }); // 自动重连实现 async function autoReconnect(relayUrl) { let retries = 3; while (retries > 0) { try { const response = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: relayUrl } }); if (response.success) return response; } catch (error) { console.log(`重连失败(${retries}次尝试剩余)`, error.message); retries--; await new Promise(res => setTimeout(res, 2000)); } } throw new Error('达到最大重连次数'); }

常见误区

❌ 错误:未设置会话超时,导致连接长期保持

✅ 正确:为生产环境设置合理的会话超时时间,建议不超过30分钟

❌ 错误:频繁创建新连接而不关闭旧连接

✅ 正确:实现连接池管理或确保每次使用后正确断开连接

进阶方案:解决复杂场景的高级技巧

协议版本兼容性处理

不同版本的扩展与服务器可能存在协议兼容性问题,可通过以下方式处理:

// 检查协议版本兼容性 const serverInfo = await client.callTool({ name: 'get_server_info' }); const requiredVersion = '1.2.0'; // 版本比较函数 function versionGreaterOrEqual(version, required) { const v1 = version.split('.').map(Number); const v2 = required.split('.').map(Number); for (let i = 0; i < v2.length; i++) { if (v1[i] > v2[i]) return true; if (v1[i] < v2[i]) return false; } return true; } if (!versionGreaterOrEqual(serverInfo.protocolVersion, requiredVersion)) { console.warn(`协议版本不兼容,需要≥${requiredVersion},当前服务器版本${serverInfo.protocolVersion}`); // 方案1: 更新服务器 // 方案2: 降低客户端协议版本要求 process.env.PWMCP_TEST_PROTOCOL_VERSION = requiredVersion; }

安全上下文共享配置

处理敏感信息时,可启用加密连接和客户端验证:

// 启用安全连接示例 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: 'wss://secure.example.com:8080', // 使用加密WebSocket clientId: 'your-secure-client-id', // 客户端标识 clientSecret: process.env.MCP_CLIENT_SECRET // 客户端密钥(从环境变量获取) } });

多会话管理策略

当需要同时管理多个会话时,可实现连接池:

class MCPConnectionPool { constructor(maxConnections = 5) { this.connections = new Map(); this.maxConnections = maxConnections; } async acquire(tabId) { // 如果已有连接,直接返回 if (this.connections.has(tabId)) { return this.connections.get(tabId); } // 达到连接上限时等待 while (this.connections.size >= this.maxConnections) { await new Promise(res => setTimeout(res, 500)); } // 创建新连接 const connection = await this.createConnection(tabId); this.connections.set(tabId, connection); // 监听连接关闭事件 connection.on('close', () => this.connections.delete(tabId)); return connection; } async createConnection(tabId) { // 实际连接创建逻辑 return client.callTool({ name: 'browser_connect', arguments: { name: 'extension', tabId } }); } release(tabId) { if (this.connections.has(tabId)) { this.connections.get(tabId).close(); this.connections.delete(tabId); } } } // 使用连接池 const pool = new MCPConnectionPool(3); // 最多同时管理3个连接 const connection = await pool.acquire(targetTabId);

常见误区

❌ 错误:在处理敏感数据时使用未加密的ws://连接

✅ 正确:生产环境应始终使用加密的wss://连接

❌ 错误:未验证服务器证书就建立安全连接

✅ 正确:实现证书验证逻辑,避免连接到恶意服务器

跨环境适配:多平台与浏览器支持

Chrome/Edge浏览器配置

Chrome和Edge浏览器的配置基本一致,主要区别在于扩展加载路径:

# Edge浏览器加载扩展的命令行参数 edge --load-extension=./packages/extension/dist --enable-extensions

Firefox浏览器支持

Firefox对Manifest V3扩展支持有限,需要使用兼容模式:

# 构建Firefox兼容版本 cd packages/extension npm run build:firefox # 在Firefox中临时加载扩展 firefox --temporary-addon ./dist-firefox

无头模式配置

在CI/CD环境中使用无头模式运行:

// 无头模式启动MCP服务器 const browser = await chromium.launch({ headless: 'new', args: ['--mcp-server=ws://0.0.0.0:8080'] });

Docker环境部署

使用Docker容器化部署MCP服务器:

# Dockerfile示例 FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN cd packages/extension && npm run build EXPOSE 8080 CMD ["node", "server.js"]

构建并运行容器:

docker build -t playwright-mcp . docker run -p 8080:8080 playwright-mcp

常见误区

❌ 错误:假设所有浏览器都支持相同的扩展功能

✅ 正确:Firefox对Manifest V3支持有限,需单独测试和适配

❌ 错误:在无头环境中尝试使用需要用户交互的功能

✅ 正确:无头环境中应使用自动授权模式,避免需要人工干预

性能优化指标:提升连接效率与稳定性

关键性能指标

监控MCP连接的关键性能指标:

  • 连接建立时间:理想状态应<500ms,超过2秒视为连接缓慢
  • 协议延迟:CDP命令往返时间应<100ms
  • 内存占用:单个连接内存使用应<40MB
  • CPU使用率:空闲时应<5%,操作时应<20%

性能优化策略

🔧目标:优化MCP连接性能

// 优化连接参数示例 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: 'ws://localhost:8080', // 启用压缩减少网络传输 compress: true, // 限制事件传输类型 allowedEvents: ['Page.*', 'Runtime.*'], // 批量处理事件 batchMode: true, batchSize: 10, batchDelay: 50 } });

资源占用监控

在浏览器中监控扩展资源使用:

  1. 打开Chrome任务管理器:Shift+Esc
  2. 找到"Playwright MCP Bridge"扩展
  3. 监控内存占用和CPU使用率
  4. 如资源占用持续增长,可能存在内存泄漏

常见误区

❌ 错误:忽略连接性能问题,认为"能连接就行"

✅ 正确:关注连接建立时间和命令响应速度,这些直接影响测试效率

❌ 错误:启用所有事件传输以获取完整数据

✅ 正确:只启用必要的事件类型,减少不必要的数据传输

与同类工具对比:MCP扩展的优势

特性Playwright MCP扩展Selenium IDEPuppeteer ConnectChrome远程调试
状态保留✅ 完整保留❌ 有限支持✅ 基本支持✅ 基本支持
操作简便性高(图形界面授权)中(录制回放)低(纯代码)低(命令行)
安全验证✅ 用户确认机制❌ 无❌ 无❌ 无
跨浏览器✅ Chrome/Edge/Firefox✅ 多浏览器❌ 仅Chrome❌ 仅Chrome
自动化集成✅ 完整Playwright API❌ 有限API✅ 部分API❌ 需自行实现
会话共享✅ 支持多客户端❌ 不支持❌ 单客户端❌ 单客户端

[!TIP] MCP扩展的核心优势在于结合了图形化授权界面与完整的Playwright API,同时提供了安全的会话共享机制,这是其他工具无法同时实现的。

版本迁移指南:从旧版本升级

v0.1.x 到 v0.2.x 的迁移

主要变化:

  • 配置参数结构调整
  • 事件名称标准化
  • 错误处理机制改进

迁移步骤:

  1. 更新依赖:
npm update playwright-mcp
  1. 修改连接参数:
// 旧版本 const connectResponse = await client.callTool({ name: 'connect_browser', params: { url: 'ws://localhost:8080', tab: 123 } }); // 新版本 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: 'ws://localhost:8080', tabId: 123 } });
  1. 更新事件监听:
// 旧版本 connection.on('pageEvent', (event) => { ... }); // 新版本 connection.on('Page.navigate', (event) => { ... }); connection.on('Runtime.consoleAPICalled', (event) => { ... });

版本兼容性矩阵

MCP扩展版本Playwright版本Node.js版本浏览器版本
v0.1.x1.30.0-1.35.016.x-18.xChrome 98-105
v0.2.x1.36.0-1.40.018.x-20.xChrome 106-112
v0.3.x≥1.41.0≥18.xChrome ≥113

常见误区

❌ 错误:直接替换扩展文件而不更新依赖

✅ 正确:完整更新npm包并检查API变更

❌ 错误:假设旧版脚本可直接在新版扩展上运行

✅ 正确:关注版本变更日志,特别是"Breaking Changes"部分

自动化集成建议:融入现有工作流

Jest测试框架集成

// jest.config.js module.exports = { testEnvironment: 'node', setupFilesAfterEnv: ['./jest.setup.js'], testMatch: ['**/*.mcp.test.js'] }; // jest.setup.js const { chromium } = require('playwright'); let browser; let mcpServer; beforeAll(async () => { // 启动MCP服务器 browser = await chromium.launch({ args: ['--mcp-server=ws://localhost:8080'] }); // 等待服务器准备就绪 await new Promise(res => setTimeout(res, 1000)); }); afterAll(async () => { await browser.close(); });

测试用例示例:

test('使用MCP扩展连接已登录会话', async () => { // 发起连接请求 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: 'ws://localhost:8080' } }); expect(connectResponse.success).toBe(true); // 在已连接会话中执行操作 const result = await client.callTool({ name: 'browser_evaluate', arguments: { expression: 'window.localStorage.getItem("userToken")' } }); // 验证用户已登录 expect(result.value).not.toBeNull(); });

GitHub Actions集成

# .github/workflows/mcp-test.yml name: MCP Extension Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Build extension run: cd packages/extension && npm run build - name: Run MCP tests run: npm test env: MCP_RELAY_URL: ws://localhost:8080 CI: true

持续集成最佳实践

  1. 使用专用测试账号保存登录状态
  2. 实现会话自动授权机制,避免CI环境中需要人工干预
  3. 为不同测试场景创建独立的MCP服务器实例
  4. 记录连接性能指标,监控系统健康状态

常见误区

❌ 错误:在CI环境中使用需要人工授权的连接方式

✅ 正确:CI环境应使用自动授权模式或预保存的会话状态

❌ 错误:所有测试共享一个MCP连接

✅ 正确:为每个测试套件创建独立连接,避免状态污染

场景拓展:MCP扩展的创新应用

场景1:保留认证状态的自动化测试

/** * 连接到已登录的电商网站标签页,测试购物流程 */ async function testShoppingFlow() { // 1. 连接到已登录的电商网站标签页 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: 'ws://localhost:8080', // 筛选标题包含"我的账户"的标签页 tabFilter: (tab) => tab.title.includes('我的账户') } }); if (!connectResponse.success) { throw new Error('连接失败: ' + connectResponse.error); } // 2. 导航到商品页面 await client.callTool({ name: 'browser_goto', arguments: { url: 'https://example.com/products/123' } }); // 3. 添加商品到购物车 await client.callTool({ name: 'browser_click', arguments: { selector: '.add-to-cart-button' } }); // 4. 验证购物车更新 const cartCount = await client.callTool({ name: 'browser_evaluate', arguments: { expression: 'document.querySelector(".cart-count").textContent' } }); console.log('购物车商品数量:', cartCount.value); expect(parseInt(cartCount.value)).toBeGreaterThan(0); }

场景2:客户支持远程协助

/** * 实现客户支持远程协助功能 */ async function startSupportSession() { // 1. 生成唯一支持会话ID const sessionId = 'support-' + Date.now(); // 2. 启动带认证的MCP服务器 const browser = await chromium.launch({ args: [ `--mcp-server=wss://support.example.com:8080`, `--mcp-auth-token=${process.env.SUPPORT_AUTH_TOKEN}`, `--mcp-session-id=${sessionId}` ] }); // 3. 生成客户连接URL const supportUrl = `https://support.example.com/connect?session=${sessionId}`; console.log('请客户访问以下URL开始支持会话:', supportUrl); // 4. 等待客户连接 const connection = await waitForSupportConnection(sessionId); // 5. 开始远程协助 console.log('客户已连接,开始远程协助'); // 6. 记录会话操作供后续分析 connection.on('event', (event) => { logSupportEvent(sessionId, event); }); return connection; }

场景3:自动化与手动操作混合测试

/** * 混合测试流程:手动完成复杂操作,自动执行验证 */ async function hybridTestingFlow() { // 1. 启动MCP服务器 const browser = await chromium.launch({ args: ['--mcp-server=ws://localhost:8080'] }); // 2. 提示测试人员完成手动操作 console.log('请在浏览器中完成以下操作:'); console.log('1. 登录系统'); console.log('2. 导航到订单管理页面'); console.log('3. 选择待处理订单'); console.log('完成后按Enter键继续...'); // 等待用户确认 await new Promise(res => process.stdin.once('data', res)); // 3. 连接到当前活跃标签页 const connectResponse = await client.callTool({ name: 'browser_connect', arguments: { name: 'extension', mcpRelayUrl: 'ws://localhost:8080', activeTab: true // 连接当前活跃标签页 } }); // 4. 自动执行验证步骤 const orderDetails = await client.callTool({ name: 'browser_evaluate', arguments: { expression: `{ id: document.querySelector('#order-id').textContent, status: document.querySelector('#order-status').textContent, items: Array.from(document.querySelectorAll('.order-item')).map(el => el.textContent) }` } }); // 5. 生成测试报告 generateTestReport({ manualSteps: '登录并选择待处理订单', automatedResults: orderDetails.value, timestamp: new Date() }); }

总结:重新定义浏览器自动化的边界

Playwright MCP扩展通过创新的会话共享技术,打破了传统自动化测试与手动操作之间的壁垒。它不仅解决了测试环境构建复杂、认证状态难以复用等实际问题,还为浏览器自动化开辟了新的应用场景,如远程协作调试、混合测试模式等。

通过本文介绍的工作机制、安装配置、实践操作和高级技巧,你已经掌握了MCP扩展的核心使用方法。无论是保留认证状态的自动化测试,还是实现远程协助功能,MCP扩展都能显著提升工作效率,降低复杂场景的处理难度。

随着Web应用复杂度的不断提升,MCP技术将在自动化测试、远程协作、客户支持等领域发挥越来越重要的作用。希望本文能帮助你充分利用这一强大工具,构建更灵活、高效的浏览器自动化工作流。

【免费下载链接】playwright-mcpPlaywright Tools for MCP项目地址: https://gitcode.com/gh_mirrors/pl/playwright-mcp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 11:00:19

Janus-Pro-7B多语言支持实战:跨语言文本生成与翻译

Janus-Pro-7B多语言支持实战&#xff1a;跨语言文本生成与翻译 当AI能够真正理解并生成多种语言时&#xff0c;世界会变得多么不同&#xff1f;想象一下&#xff0c;一个模型不仅能读懂中文诗歌&#xff0c;还能用法语写出同样优美的诗句&#xff0c;甚至将西班牙语的技术文档准…

作者头像 李华
网站建设 2026/8/30 11:02:08

N_m3u8DL-RE:跨平台流媒体下载高效解决方案

N_m3u8DL-RE&#xff1a;跨平台流媒体下载高效解决方案 【免费下载链接】N_m3u8DL-RE 跨平台、现代且功能强大的流媒体下载器&#xff0c;支持MPD/M3U8/ISM格式。支持英语、简体中文和繁体中文。 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE 副标题…

作者头像 李华
网站建设 2026/8/30 11:03:12

HY-Motion 1.0与Blender联动教程:生成的BVH文件如何导入使用?

HY-Motion 1.0与Blender联动教程&#xff1a;生成的BVH文件如何导入使用&#xff1f; 你刚刚用HY-Motion 1.0生成了一段惊艳的3D动作&#xff0c;看着预览视频里的人物流畅地行走、跳跃&#xff0c;成就感满满。但兴奋过后&#xff0c;一个现实问题摆在眼前&#xff1a;这个.b…

作者头像 李华
网站建设 2026/8/28 17:03:55

浦语灵笔2.5-7B高性能:双卡并行使batch_size翻倍,吞吐提升2.1倍

浦语灵笔2.5-7B高性能&#xff1a;双卡并行使batch_size翻倍&#xff0c;吞吐提升2.1倍 1. 模型概述与技术亮点 浦语灵笔2.5-7B是上海人工智能实验室开发的多模态视觉语言大模型&#xff0c;基于InternLM2-7B架构&#xff0c;融合了CLIP ViT-L/14视觉编码器。这个模型最大的特…

作者头像 李华