H5实现录屏功能代码

该代码示例展示了如何在HTML文件中利用JavaScript的MediaRecorderAPI和navigator.mediaDevices.getDisplayMedia方法实现简单的屏幕录制和下载功能。用户可以点击按钮开始和停止录制,录制的视频会自动播放并提供下载选项。
该文章已生成可运行项目,

 复制下面的代码至html文件,然后直接打开html文件即可使用录屏功能

<!DOCTYPE html>
<html lang="zh-CN">
<head>
   <meta charset="utf-8">
   <title>屏幕录制</title>
   <style>
       body{
           font-family: Arial;
           margin: 4vh auto;
           width: 90vw;
           max-width: 600px;
           text-align: center;
       }
       #controls{
           text-align: center;
       }
       .btn{
           margin: 10px 5px;
           padding: 15px;
           background-color: #2bcbba;
           border: none;
           color: white;
           font-weight: bold;
           border-radius: 6px;
           outline: none;
           font-size: 1.2em;
           width: 120px;
           height: 50px;
       }
       .btn:hover{
           background-color: #26de81;
           cursor: hand;
       }
       .btn:disabled{
           background-color: #2bcbba80;
       }
       #stop{
           background-color: #fc5c65;
       }
       #video{
           margin-top: 10px;
           margin-bottom: 20px;
           border: 12px solid #a5adb0 ;
           border-radius: 15px;
           outline: none;
           width: 100%;
           height: 400px;
           background-color: black;
       }
       h1{
           color: #2bcbba;
           letter-spacing:-2.5px;
           line-height: 30px;
       }
       .created{
           color: lightgrey;
           letter-spacing: -0.7px;
           font-size: 1em;
           margin-top: 40px;
       }
       .created > a{
           color: #4b7bec;
           text-decoration: none;
       }
   </style>
</head>

<body>
<video autoplay='true' id='video' controls='true' controlsList='nodownload'></video>
<button class='btn' id='record' onclick='record()'>录制</button>
<button style='display: none' class='btn' id='stop' onclick='stop()'>停止</button>
<button disabled='true' class='btn' id='download' onclick='download()'>下载</button>
<div class='created'>  </div>
<footer>
    
</footer>
</body>
<script>
const video = document.getElementById('video')
const downloadBtn = document.getElementById('download')
const recordBtn = document.getElementById('record')
const stopBtn = document.getElementById('stop')
let recorder

async function record() {
  // 开始录屏
  let captureStream

  try{
    captureStream = await navigator.mediaDevices.getDisplayMedia({
      video: true,
      // audio: true,   not support
      cursor: 'always'
    })
  }catch(e){
    // 取消录屏或者报错
    alert("Could not get stream")
    return
  }

  downloadBtn.disabled = true
  recordBtn.style = 'display: none'
  stopBtn.style = 'display: inline'

  // 删除之前的 Blob
  window.URL.revokeObjectURL(video.src)

  video.autoplay = true

  // 实时的播放录屏
  video.srcObject = captureStream

  // new 一个媒体记录
  recorder = new MediaRecorder(captureStream)
  recorder.start()

  captureStream.getVideoTracks()[0].onended = () => {
    // 录屏结束完成
    recorder.stop()
  }

  recorder.addEventListener("dataavailable", event => {
    // 录屏结束,并且数据可用
    console.log("dataavailable------------")
    let videoUrl = URL.createObjectURL(event.data, {type: 'video/ogg'})

    video.srcObject = null
    video.src = videoUrl
    video.autoplay = false

    downloadBtn.disabled = false
    recordBtn.style = 'display: inline'
    stopBtn.style = 'display: none'
  })
}

function download(){
  // 下载
  const url = video.src
  const name = new Date().toISOString().slice(0, 19).replace('T',' ').replace(" ","_").replace(/:/g,"-")
  const a = document.createElement('a')

  a.style = 'display: none'
  // a.download = `${name}.ogg`
  a.download = `${name}.mp4`
  a.href = url

  document.body.appendChild(a)

  a.click()
}

function stop(){
  let tracks = video.srcObject.getTracks()
  tracks.forEach(track => track.stop())
  recorder.stop()
}
</script>
</html>

 效果:

 

本文章已经生成可运行项目
<think>我们正在构建一个H5应用,使用Vue3 + TypeScript + Vite,需要实现功能,并且要兼容微信内置浏览器和其他主流浏览器。 功能通常使用WebRTC的getDisplayMedia API来实现,但需要注意兼容性问题,特别是在微信浏览器中。 步骤: 1. 检查浏览器是否支持getDisplayMedia 2. 在微信浏览器中,由于微信的内置策略,可能无法直接使用,需要做特殊处理(例如使用微信的JS-SDK?但微信JS-SDK目前没有提供接口) 3. 对于不支持getDisplayMedia的浏览器,可能需要使用第三方库或者提示用户使用其他浏览器 考虑到兼容性,我们可以: - 尝试使用getDisplayMedia,并处理不同浏览器的前缀问题 - 对于微信浏览器,由于安全限制,可能无法直接,需要引导用户使用其他浏览器(如QQ浏览器、Chrome等) 实现方案: 1. 使用navigator.mediaDevices.getDisplayMedia来捕获幕流(注意:在非安全环境(如http)下,这个API可能不可用,因此需要https) 2. 将捕获的媒体流制下来,可以使用MediaRecorder API 但是,微信浏览器中,getDisplayMedia目前不被支持(根据2023年的情况)。因此,我们需要在微信中提供替代方案,或者提示用户。 具体步骤: 1. 检测环境:判断是否在微信浏览器中,以及是否支持getDisplayMedia 2. 在支持getDisplayMedia的浏览器中,使用原生API进行 3. 在微信浏览器中,我们可以尝试使用微信的JS-SDK?但是微信JS-SDK目前没有提供幕捕获的接口。因此,可能需要引导用户使用其他浏览器。 另一种思路:使用第三方服务(如提供SDK的云服务),但这样会增加依赖和成本。 因此,我们决定: - 在支持getDisplayMedia的浏览器中,使用原生API实现。 - 在微信浏览器中,提示用户使用其他浏览器。 代码实现: 1. 请求幕共享 2. 创建MediaRecorder对象进行3. 将制的数据保存为视频文件 注意:在iOS上,Safari直到15.4版本才部分支持getDisplayMedia,且仅支持捕获整个幕,不支持单个应用窗口。因此,需要检查iOS版本。 我们使用以下步骤: 步骤1:检测浏览器支持情况 步骤2:获取幕流 步骤3幕流 步骤4:生成视频文件 同时,由于Vite项目,我们使用TypeScript,所以需要定义类型。 具体代码结构: 我们创建一个useScreenRecorder的Composable函数(使用Vue3的组合式API)。 伪代码: 1. 定义状态:recording(是否正在制)、stream(媒体流)、mediaRecorder(制对象)、videoBlob(制的视频数据) 2. 开始制:async function startRecording() - 尝试获取幕流:stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true/false? }) - 创建MediaRecorder对象,设置制的事件处理(ondataavailable事件,将数据块收集起来) - 开始3. 停止制:function stopRecording() - 停止mediaRecorder - 关闭stream中的轨道 - 将收集的数据块生成Blob 4. 下载视频:提供一个下载方法 但是,在微信浏览器中,navigator.mediaDevices.getDisplayMedia是不存在的,所以我们需要在开始前检查。 兼容性处理: - 检查navigator.mediaDevices以及getDisplayMedia是否存在 - 也可以检查userAgent,如果是微信浏览器,则提示 我们可以在开始制前进行支持性检查,如果不支持,则提示用户。 实现: 创建hooks/useScreenRecorder.ts 代码: */</think>基于您的需求,我将为您提供在 Vue3 + TypeScript + Vite 的 H5 应用中实现功能的完整解决方案,并分析微信浏览器和其他浏览器的兼容性。 ### 一、功能实现方案 #### 1. 核心 API 选择 H5 主要依赖 **WebRTC** 的 `getDisplayMedia` API: ```typescript // 请求幕共享权限 const startRecording = async () => { try { const stream = await navigator.mediaDevices.getDisplayMedia({ video: { cursor: "always" }, audio: true // 是否制系统声音 }); return stream; } catch (error) { console.error("权限被拒绝:", error); } } ``` #### 2. 完整组件实现 ```vue <template> <div> <button @click="toggleRecording"> {{ isRecording ? &#39;停止&#39; : &#39;开始&#39; }} </button> <video ref="preview" controls muted class="preview-video"></video> </div> </template> <script lang="ts" setup> import { ref } from &#39;vue&#39;; const isRecording = ref(false); const mediaRecorder = ref<MediaRecorder | null>(null); const recordedChunks = ref<Blob[]>([]); const preview = ref<HTMLVideoElement | null>(null); // 开始/停止 const toggleRecording = async () => { if (isRecording.value) { stopRecording(); } else { await startRecording(); } }; // 开始制 const startRecording = async () => { try { const stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true }); // 显示预览 if (preview.value) { preview.value.srcObject = stream; } // 创建制器 mediaRecorder.value = new MediaRecorder(stream, { mimeType: &#39;video/webm;codecs=vp9&#39; }); mediaRecorder.value.ondataavailable = (event) => { if (event.data.size > 0) { recordedChunks.value.push(event.data); } }; mediaRecorder.value.onstop = () => { saveRecording(); stream.getTracks().forEach(track => track.stop()); }; mediaRecorder.value.start(); isRecording.value = true; } catch (err) { console.error(&#39;启动失败:&#39;, err); } }; // 停止制 const stopRecording = () => { if (mediaRecorder.value) { mediaRecorder.value.stop(); isRecording.value = false; } }; // 保存制文件 const saveRecording = () => { const blob = new Blob(recordedChunks.value, { type: &#39;video/webm&#39; }); const url = URL.createObjectURL(blob); const a = document.createElement(&#39;a&#39;); a.href = url; a.download = `-${new Date().toISOString().slice(0, 19)}.webm`; document.body.appendChild(a); a.click(); // 清理 URL.revokeObjectURL(url); document.body.removeChild(a); recordedChunks.value = []; }; </script> ``` ### 二、浏览器兼容性分析 #### 1. 桌面浏览器支持情况 | 浏览器 | `getDisplayMedia` 支持 | 备注 | |---------------|------------------------|-------------------------------| | Chrome 89+ | ✅ 完全支持 | 最佳支持 | | Firefox 76+ | ✅ 支持 | 需启用`media.navigator`标志 | | Edge 79+ | ✅ 支持 | Chromium内核版本 | | Safari 13+ | ⚠️ 部分支持 | 需手动启用幕共享功能[^1] | | Opera 66+ | ✅ 支持 | | #### 2. 移动浏览器支持 | 浏览器 | 支持情况 | 特殊说明 | |-----------------|----------|----------| | Chrome Android | ✅ | 最佳体验 | | Firefox Android | ⚠️ | 功能受限 | | Safari iOS | ❌ | 完全不支持 | | **微信内置浏览器** | ⚠️ | 需要特殊处理 | ### 三、微信浏览器兼容方案 微信浏览器存在特殊限制,需额外处理: #### 1. 微信中启用 ```typescript // 检测微信环境 const isWeChatBrowser = /MicroMessenger/i.test(navigator.userAgent); // 微信特殊处理 if (isWeChatBrowser) { // 方案1: 使用微信JS-SDK(需企业认证) wx.ready(() => { wx.startRecordScreenCapture({ success: () => console.log(&#39;已启动&#39;), fail: (err) => console.error(&#39;微信失败&#39;, err) }); }); // 方案2: 引导用户使用系统浏览器打开 else { showModal(&#39;提示&#39;, &#39;请在右上角菜单中选择"在浏览器打开"&#39;); } } ``` #### 2. 微信兼容性注意事项 1. **权限限制** 微信内置浏览器默认禁用 `getDisplayMedia`,需引导用户: ```html <div v-if="isWeChatBrowser" class="wechat-tip"> <p>请点击右上角 ⋮ 选择「在浏览器打开」</p> <img src="wechat-guide.png" alt="微信操作指引"> </div> ``` 2. **备选方案** 对于必须微信内使用的场景: ```typescript // 使用替代API(需用户授权) const wechatScreenCapture = () => { const input = document.createElement(&#39;input&#39;); input.type = &#39;file&#39;; input.accept = &#39;video/*&#39;; input.capture = &#39;screen&#39;; input.onchange = (e) => { // 处理文件 }; input.click(); } ``` ### 四、Vite 项目优化配置 #### 1. tsconfig.json 关键配置 ```json { "compilerOptions": { "types": ["vite/client"], "lib": ["DOM", "ES2020"], "target": "ESNext" } } ``` #### 2. 依赖安装 ```bash npm install weixin-js-sdk @types/weixin-js-sdk -D ``` #### 3. 解决iOS兼容性问题 ```typescript // src/utils/screenCapture.ts export const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); export const getSupportedMimeType = () => { const types = [ &#39;video/webm;codecs=vp9&#39;, &#39;video/mp4;codecs=avc1&#39;, &#39;video/mp4&#39; ]; return types.find(type => MediaRecorder.isTypeSupported(type) ) || &#39;&#39;; }; ``` ### 五、最佳实践建议 1. **降级方案** 当检测到不支持时: ```vue <template> <div v-if="!isSupported"> <p>您的浏览器不支持功能</p> <button @click="downloadApp">下载客户端</button> </div> </template> ``` 2. **权限引导优化** 使用异步检测: ```typescript const checkPermissions = async () => { const hasVideo = await navigator.permissions.query({ name: &#39;display-capture&#39; as PermissionName }); return hasVideo.state === &#39;granted&#39;; } ``` 3. **制参数优化** 根据设备性能调整: ```typescript const constraints = { video: { width: { ideal: 1280 }, height: { ideal: 720 }, frameRate: { ideal: 24, max: 30 } }, audio: { sampleRate: 44100, channelCount: 2 } }; ``` ### 六、安全注意事项 1. **HTTPS 强制要求** `getDisplayMedia` 只能在安全上下文(HTTPS)中使用 2. **用户提示规范** 需明确告知用户: ```typescript const showConsentDialog = () => { if (!localStorage.getItem(&#39;screen-record-consent&#39;)) { if (confirm(&#39;您即将分享幕内容...&#39;)) { localStorage.setItem(&#39;screen-record-consent&#39;, &#39;true&#39;); } } } ``` 3. **数据隐私保护** 数据应: - 本地处理,不上传云端 - 添加水印标识 - 自动删除过期记 > **总结**:在 Vue3 + TS + Vite 项目中实现 H5 ,核心是合理使用 `getDisplayMedia` API,针对微信浏览器需特殊处理。桌面端 Chrome/Firefox 支持最佳,移动端需引导用户使用系统浏览器,iOS 和微信内置浏览器支持度有限,建议提供替代方案或客户端引导[^1][^2]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值