在微信小程序里用 xr-frame 实现"图片识别播放视频",核心是用 2D Marker 图像识别模式,当摄像头识别到特定图片时,在图片位置播放视频。xr-frame 官方提供了 Marker 模式和视频纹理支持,正好可以实现这个功能。
下面是具体的步骤和可直接运行的代码。
第一步:环境与权限配置
和之前的 AR 功能一样,需要先做好基础配置:
工具与基础库:使用微信开发者工具,小程序基础库版本不低于 2.32.0,这是 xr-frame 功能稳定的版本。
项目配置:在 app.json 中声明相机权限:
// app.json
{
"permission": {
"scope.camera": {
"desc": "需要使用您的相机实现AR效果"
}
}
}
第二步:核心代码实现
这是最关键的一步,通过 xr-frame 的声明式组件来搭建场景。代码主要分为三个部分:加载视频纹理、配置图像追踪器、让视频在识别成功后播放。
核心代码 (index.wxml):
<!-- 开启AR系统,并设置为2D Marker识别模式 -->
<xr-scene ar-system="modes:Marker" bind:ready="handleReady">
<!-- 1. 资源加载区 -->
<xr-assets bind:loaded="handleAssetsLoaded">
<!-- 加载视频纹理,asset-id 是它的唯一标识 -->
<xr-asset-load
type="video-texture"
asset-id="my-video"
src="https://your-domain.com/your-video.mp4"
options="loop:true"
/>
<!-- 创建一个材质,并将视频纹理作为颜色贴图绑定上去 -->
<!-- 注意:u_baseColorMap 的值是 "video-" 加上视频的 asset-id -->
<xr-asset-material
asset-id="video-mat"
effect="simple"
uniforms="u_baseColorMap: video-my-video"
/>
</xr-assets>
<!-- 2. 图像追踪器:当识别到 src 指定的图片时,显示视频画面 -->
<!-- 使用 wx:if 控制追踪器在资源加载完成后才显示,优化体验 -->
<xr-node wx:if="{{loaded}}">
<xr-ar-tracker
mode="Marker"
bind:ar-tracker-switch="handleTrackerSwitch"
src="https://your-domain.com/marker.jpg"
>
<!-- 一个平面网格,用来承载视频画面 -->
<!-- 材质使用前面创建的 video-mat,视频纹理就会显示在上面 -->
<xr-mesh geometry="plane" material="video-mat" />
</xr-ar-tracker>
</xr-node>
<!-- 3. AR相机 -->
<xr-camera background="ar" is-ar-camera />
</xr-scene>
代码要点说明:
-
<xr-asset-load type="video-texture">:加载视频文件。视频文件需放在网络服务器或云存储上,通过 src 引用。 -
<xr-asset-material>:创建了一个简单的材质,关键在 uniforms="u_baseColorMap: video-my-video",这行代码将前面加载的视频纹理作为贴图绑定到材质上。video- 前缀是固定写法,后面必须跟视频的 asset-id。 -
<xr-ar-tracker mode="Marker">:图像追踪器,mode="Marker" 指定为2D图像识别模式。src 属性指向你的识别图,当摄像头画面中出现该图片时,内部节点(视频画面)就会显示在图片位置上。 -
wx:if="{``{loaded}}"和bind:ar-tracker-switch:通过JS控制视频播放时机,在识别成功后才开始播放,体验更好。
第三步:JS逻辑控制
在JS文件中,需要配合 WXML 的逻辑,控制视频在识别成功后才开始播放。
页面逻辑 (index.js):
Page({
data: {
loaded: false, // 控制视频资源是否加载完成
},
// 场景准备就绪
handleReady({ detail }) {
// 可以获取场景实例进行更高级的控制
// const scene = detail.value;
},
// 资源加载完成
handleAssetsLoaded() {
// 资源加载完成后,显示追踪器(触发 wx:if)
this.setData({ loaded: true });
},
// 追踪器状态切换(识别成功/丢失)
handleTrackerSwitch({ detail }) {
const active = detail.value; // true: 识别成功, false: 识别丢失
// 通过 asset-id 获取视频纹理实例
const video = this.scene?.assets.getAsset('video-texture', 'my-video');
if (video) {
active ? video.play() : video.stop();
}
}
});
进阶与注意事项
-
视频与图片比例:默认的 plane 几何体是 1x1 的正方形。如果你的视频是 16:9 的,需要通过 xr-mesh 的 scale 属性调整长宽比(例如 scale="1.6 1 1")避免拉伸。
-
识别图选择:Marker 模式适合识别纹理丰富、边缘清晰的平面物体,比如海报、卡片、书本封面等。识别图本身不一定要在 xr-assets 中预先加载,可以直接写在 src 里。
-
真机调试:AR 功能必须在真机上预览和测试,开发者工具中的模拟器无法模拟相机和追踪效果。
-
动态切换视频:如果你需要根据识别结果动态切换不同的视频,xr-asset-load 的 src 无法直接动态修改。官方推荐的方式是通过 scene.assets.loadAsset() API 在 JS 中动态加载视频纹理,并重新创建材质。