Skip to content

SDK Examples

本页演示了 Sib Scanne SDK 提供的一些运行时 API 的使用方法。

安装

使用你喜欢的包管理工具

bash
# npm
npm install sib-scanne-sdk

#yarn
yarn add sib-scanne-sdk

#pnpm
pnpm add sib-scanne-sdk

#bun
bun add sib-scanne-sdk

配置选项

handleError 参数 (callback)

属性类型默认值说明
-callback: (error: Error) => void-sdk 中所有的错误都会通过 handleError 函数抛出

createScanner 参数(createOptions)

属性类型默认值说明
-createOptions?: ReaderOptions{}扫描器创建时的配置参数

start 方法参数(startOption)

属性类型默认值说明
videoHTMLVideoElement-必须传入的视频元素,用于展示摄像头画面
deviceIdstring-可选,指定要使用的摄像头设备 ID(可通过 getDevices 方法获取)
constraintsMediaTrackConstraints-可选,摄像头约束配置(如分辨率、帧率等)
readerOptionsReaderOptions-可选,摄像头约束配置(如分辨率、帧率等)

扫描器实例方法

方法名类型说明
start(startOption: StartOption) => Promise<void>启动扫描器,传入视频元素及相关配置
decodeDatacallback: (result: ReadResult[], imageSource?: ImageData | null) => void获取解码结果的方法
getDevices() => Promise<MediaDeviceInfo[]>获取所有可用摄像头设备列表
stop() => void停止解码和 Canvas 绘画
destroy() => void销毁扫描器实例,清除元素、流及所有属性

在项目中使用

你可以在 Vue或者React或者原生html中使用

Vue

Vue
<template>
    <video
        muted
        autoplay
        playsinline
        webkit-playsinline
        ref="videoElement"
        poster="data:image/gif,AAAA"
        class="absolute inset-0 w-full h-full object-cover bg-black z-50"
    ></video>
</template>

<script setup lang="ts">
import { onMounted, useTemplateRef, computed } from 'vue'
import { handleError, createScanner } from 'sib-scanne-sdk'
import type { Position, ReadResult } from 'sib-scanne-sdk'

const videoRef = useTemplateRef<HTMLVideoElement>('videoElement')
const scanner = createScanner() // 创建扫码实例
onMounted(async () => {
    try {
        const { start, stop, destroy, decodeData, getDevices } = scanner
        await start({ video: videoRef.value })
        // 获取摄像头列表
        const devices: Promise<MediaDeviceInfo[]> = await getDevices()
        console.log(
            '==>devices',
            devices.map(device => ({ label: device.label, deviceId: device.deviceId })),
        )
        // 解码
        decodeData((results: ReadResult[] , imageBitmap: ImageData) => {
            if (results && Array.isArray(results) && results.length > 0) {
                console.log(results[0].text) // 解码结果
                stop() // 停止解码 | 停止媒体流绘制
                destroy() // 销毁实例
                // ....
            }
        })
    } catch (error) {
        console.error(error)
        // ...
    }
})

// 错误处理
handleError(error => {
    console.error(error)
    // ....
})
</script>

React

tsx
import { useEffect, useRef } from "react";
import { createScanner, handleError, ReadResult } from "sib-scanne-sdk";

export default function ScannerVideo() {
  const videoRef = useRef<HTMLVideoElement>(null);

  useEffect(() => {
    const scanner = createScanner();
    (async () => {
      try {
        const { start, stop, destroy, decodeData, getDevices } = scanner;
        await start({ video: videoRef.current! });
        console.log(
          "==>devices",
          (await getDevices()).map(d => ({ label: d.label, deviceId: d.deviceId }))
        );

        decodeData((results: ReadResult[]) => {
          if (results?.length) {
            console.log("扫码结果:", results[0].text);
            stop();
            destroy();
          }
        });
      } catch (err) {
        console.error("scanner error:", err);
      }
    })();
    handleError(err => console.error("scanner handleError:", err));
    return () => {
      try {
        scanner.stop();
        scanner.destroy();
      } catch {}
    };
  }, []);

  return (
    <video
      ref={videoRef}
      muted
      autoPlay
      playsInline
      poster="data:image/gif,AAAA"
      className="absolute inset-0 w-full h-full object-cover bg-black z-50"
    />
  );
}

HTML

html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <video src="./test.mp4" id="video" controls autoplay></video>
        <script src="sib-scanne-sdk.umd.cjs"></script>
        <script>
            const { createScanner, handleError } = window.SibScanne
            handleError((error) => console.error(error))  // 错误监听
            const scanner = createScanner(/* options */)  // 初始化
            window.onload = function () {
                ; (async () => {
                    const video = document.getElementById('video')
                    await scanner.start({ video })
                    // 解码
                    scanner.decodeData((results: ReadResult[] , imageBitmap: ImageData) => {
                        if (results && Array.isArray(results) && results.length > 0) {
                            console.log(results[0].text) // 解码结果
                            scanner.stop() // 停止解码 | 停止媒体流绘制
                            scanner.destroy() // 销毁实例
                            // ....
                        }
                    })
                })()
            }
        </script>
    </body>
</html>

常见问题

相机无法启动,扫描不到 Code?

若遇到相机无法启动、无法扫描 Code 的问题,可按以下步骤排查:

1、基础检查

  1. 浏览器权限设置:查看浏览器地址栏左侧(如锁形图标处),确认相机权限为“允许”;部分系统(如 macOS、Windows)需在系统设置的“隐私与安全性 - 相机”中,允许对应浏览器访问相机。
  2. HTTPS 连接:现代浏览器仅允许在 HTTPS 协议(公网)或 localhost/127.0.0.1(本地开发)下访问相机,若为本地文件(file:// 协议),需启动本地服务(如 Vite 开发服务器)。
  3. 浏览器兼容性:推荐使用 Chrome 100+Edge 100+ 等现代浏览器,旧版或小众浏览器可能对相机 API 支持不足。

2、调试代码

可通过以下代码获取摄像头设备列表,排查设备是否被正确识别:

javascript
// 获取并打印所有媒体设备(含摄像头)
navigator.mediaDevices.enumerateDevices().then(devices => {
  // 筛选出摄像头设备
  const cameras = devices.filter(device => device.kind === 'videoinput');
  console.log('可用摄像头列表:', cameras);

  // 若无摄像头设备
  if (cameras.length === 0) {
    console.error('未检测到任何摄像头设备');
    alert('当前设备无可用摄像头,请检查硬件连接');
    return;
  }

  // 打印摄像头详细信息(设备ID、名称等)
  cameras.forEach(camera => {
    console.log(`设备ID:${camera.deviceId},设备名称:${camera.label || '未知摄像头'}`);
  });
}).catch(error => {
  console.error('获取设备列表失败:', error);
  alert('无法读取摄像头设备信息,请检查浏览器权限');
});

3、补充说明

  • 多摄像头场景:若设备有多个摄像头(如手机前后置、PC 外接摄像头),可通过上述代码的 device.label 区分设备,再结合需求指定摄像头(如优先选后置摄像头)。
  • iframe 嵌套:若相机功能在 iframe 中,需为 iframe 标签添加 allow="camera" 属性,否则父页面权限无法传递到 iframe。

Released under the MIT License.