UniApp中使用`live-pusher`实现实时摄像头预览与图像识别的完整技术文档

4,946 阅读5分钟

概述

本文档介绍了如何在UniApp中使用live-pusher实现一个带有摄像头预览、拍照和图像识别功能的页面。本示例主要通过前后摄像头切换、抓拍、图像识别API调用和动画提示来提供用户友好的体验,适用于类似拍照识别卡路里等应用场景。

本文档将详细介绍:

  1. 如何使用live-pusher实现实时摄像头预览和控制。
  2. 如何进行图像的抓拍和保存。
  3. 如何将抓拍的图像传递到API进行图像识别。
  4. 如何结合动画和用户交互提示,优化用户体验。

功能需求

  • 实时摄像头预览:可以通过前后摄像头实时查看视频流。
  • 抓拍照片:用户可以通过按钮抓拍照片,并保存照片用于后续处理。
  • 翻转摄像头:支持在前置和后置摄像头之间切换。
  • 显示动画:在识别过程中,显示一个提示动画。
  • 图像识别:抓拍图片后,传递给图像识别API进行识别。
  • 结果展示:在识别完成后,显示识别结果,如食物卡路里等。

页面布局和代码结构

1. 模板结构

通过<live-pusher>标签实现视频预览和拍摄功能。以下是核心的页面模板结构,包括实时摄像头的预览、提示信息、功能按钮和拍摄后的图片展示。

html
复制代码
<template>
	<view class="live-camera">
		<!-- 实时摄像头预览 -->
		<live-pusher id="livePusher" ref="livePusher" class="livePusher" mode="FHD" beauty="0" whiteness="0"
			:aspect="aspect" min-bitrate="1000" audio-quality="16KHz" :device-position="devicePosition"
			:auto-focus="true" :muted="true" :enable-camera="true" :enable-mic="false" :zoom="true"
			@statechange="statechange" :style="{ width: windowWidth , height: windowHeight }">
		</live-pusher>

		<!-- 提示信息 -->
		<view class="intro" v-if="!snapshotTaken">
			<image class="intro-image" :src="getImageSrc('camera.png')" lazy-load="true"></image>
			<text class="intro-text">{{$t('home.scan_food_calories')}}</text>
		</view>

		<!-- 抓拍的照片显示 -->
		<view class="snapshot-container" v-if="snapshotTaken">
			<image class="snapshot-image" :src="snapshotsrc" mode="aspectFit" :style="{ width: snapshotWidth, height: snapshotHeight }"></image>
			<view class="snapshot-bg"></view>
		</view>

		<!-- 动画展示 -->
		<view v-if="isAnimation" class="animationView">
			<animation-view class="animation-image" :path="pathjiqiren" :loop="true" :autoplay="true"></animation-view>
			<text class="title">{{$t('home.recognizing_in_progress')}}</text>
		</view>

		<!-- 底部操作按钮 -->
		<view class="menu" v-if="!snapshotsrc">
			<view class="menu-cent">
				<text class="cent-title">{{$t('home.photo_recognition_calories')}}</text>
			</view>
			<view class="menu-bottom">
				<image class="menu-mask" @tap="goPhoto" :src="getImageSrc('xiangce.png')" lazy-load="true"></image>
				<image class="menu-photo" @tap="takePhoto" :src="getImageSrc('scan-photo.png')" lazy-load="true"></image>
				<image class="menu-flip" @tap="record" :src="getImageSrc('scanRecord.png')" lazy-load="true"></image>
			</view>
		</view>
	</view>
</template>

说明:

  • <live-pusher>:用于实时摄像头预览,提供视频流。用户可以通过点击按钮进行抓拍操作。
  • v-if="!snapshotTaken":用于控制页面上的元素展示,未拍摄时展示提示,拍摄后隐藏提示并显示图片。
  • menu-bottom:底部操作按钮区域,包含翻转摄像头、拍照和进入相册功能。

2. JavaScript逻辑

页面的核心功能由以下逻辑实现,主要涉及摄像头的初始化、拍照、图片识别和摄像头切换。

javascript
复制代码
<script>
	import {
		pathToBase64
	} from 'image-tools'; // 用于将图片转换为Base64格式
	import {
		chatFreeImageOCRAPI
	} from '@/api/ocr.js'; // 引入用于图像识别的API

	export default {
		data() {
			return {
				devicePosition: "front", // 前置或后置摄像头, "front"表示前置, "back"表示后置
				snapshotTaken: false, // 是否已抓拍照片
				snapshotsrc: null, // 抓拍的照片路径
				isAnimation: false, // 是否正在显示动画
				windowWidth: '', // 屏幕宽度
				windowHeight: '', // 屏幕高度
				animationTop: '', // 动画的位置
			};
		},
		onReady() {
			this.livePusher = uni.createLivePusherContext('livePusher', this);
			this.initCamera();
		},
		methods: {
			// 初始化相机
			initCamera() {
				const res = uni.getSystemInfoSync();
				this.windowWidth = res.windowWidth;
				this.windowHeight = res.windowHeight;
				this.snapshotWidth = res.windowWidth;
				this.snapshotHeight = res.windowHeight;
			},
			
			// 拍照并处理图片
			takePhoto() {
				this.livePusher.snapshot({
					success: (e) => {
						uni.saveFile({
							tempFilePath: e.tempImagePath,
							success: (res) => {
								this.snapshotsrc = res.savedFilePath;
								this.snapshotTaken = true;
								this.isAnimation = true;
								this.convertImageToBase64(res.savedFilePath).then(base64 => {
									this.detectImageSubjectChatgpt(base64);
								});
							}
						});
					}
				});
			},

			// 图像识别
			async detectImageSubjectChatgpt(base64Image) {
				try {
					const response = await chatFreeImageOCRAPI({ imageStr: base64Image });
					this.handleChatgptResponse(response);
				} catch (error) {
					console.error('图像识别失败:', error);
				}
			},

			// 切换摄像头
			flip() {
				this.livePusher.switchCamera();
			},

			// 图片转为Base64
			convertImageToBase64(filePath) {
				return pathToBase64(filePath);
			}
		}
	}
</script>

3. 核心逻辑分析

3.1 摄像头预览与初始化

  • 使用uni.createLivePusherContext初始化live-pusher上下文,通过onReady生命周期调用。
  • 使用uni.getSystemInfoSync()获取设备屏幕宽高,以保证摄像头视频预览与屏幕尺寸适配。
javascript
复制代码
onReady() {
	this.livePusher = uni.createLivePusherContext('livePusher', this);
	this.initCamera();
}

3.2 拍照功能

  • 通过livePusher.snapshot()方法进行拍照。
  • 拍照后,使用uni.saveFile()将图片存储到本地,之后通过API将图片转换为Base64进行识别。
javascript
复制代码
takePhoto() {
	this.livePusher.snapshot({
		success: (e) => {
			uni.saveFile({
				tempFilePath: e.tempImagePath,
				success: (res) => {
					this.snapshotsrc = res.savedFilePath;
					this.snapshotTaken = true;
					this.isAnimation = true;
					this.convertImageToBase64(res.savedFilePath).then(base64 => {
						this.detectImageSubjectChatgpt(base64);
					});
				}
			});
		}
	});
}

3.3 图像识别

  • 图片抓拍后,通过API调用图像识别接口,将图片的Base64数据传递给服务器,获取识别结果。
  • 当识别完成后,通过回调函数处理识别结果。
javascript
复制代码
async detectImageSubjectChatgpt(base64Image) {
	try {
		const response = await chatFreeImageOCRAPI({ imageStr: base64Image });
		this.handleChatgptResponse(response);
	} catch (error) {
		console.error('图像识别失败:', error);
	}
}

3.4 摄像头翻转

  • livePusher.switchCamera()用于在前置和后置摄像头之间切换,提升用户体验。
javascript
复制代码
flip() {
	this.livePusher.switchCamera();
}

样式设计

4.1 摄像头界面布局

live-pusher被设置为全屏以覆盖整个视图,同时通过一些定位样式确保其他元素如按钮、提示信息等正确显示。

css
复制代码
.live-camera {
	position: relative;
	justify-content: center;
	align-items: center;
	background-color: #000000;
}

.livePusher {
	width: 100%;
	height: 100%;
}

4.2 动画布局

在用户拍摄后,为了提示用户图片正在识别中,页面会展示一个居中的动画。该动画通过animation-view组件实现,并通过动态样式调整动画的位置。

css
复制代码
.animationView {
	display: flex;
	flex-direction: column;
	position: fixed;
	width: 750rpx;
	top: 0;
	bottom: 0;
	z-index: 20;
	align-items: center;
	justify-content: center;
	background-color: rgba(0, 0, 0, 0.5);
}

5. 注意事项与优化建议

5.1 摄像头权限处理

  • 在部分设备上,用户可能需要授予摄像头权限。建议在摄像头启动前,检测并请求用户权限,并提供相关引导。

5.2 异常处理

  • 当摄像头启动失败或拍照失败时,需给出明确的提示,如“摄像头启动失败,请重试”等。
  • 在使用图像识别API时,确保处理网络请求的异常情况,避免因网络问题导致用户体验不佳。

5.3 用户体验优化

  • 加入动画提示可以提升用户体验,尤其是在图像识别过程中,展示正在识别的动画能够缓解用户等待的焦虑。
  • 在抓拍成功后立即展示拍摄的图片,并附带识别结果,使用户感受到流畅的操作反馈。

6. 总结

通过UniApp中的live-pusher组件和其他配套API,我们可以轻松实现一个集实时预览、拍照、图像识别等功能于一体的应用场景。本文从页面结构、逻辑实现、样式布局和优化建议等方面,详细阐述了如何设计和实现这样一个功能模块。在实际开发中,可以根据业务需求进一步扩展和优化,以提供更为完善的用户体验。