美顔エフェクトミニプログラムの実践

準備作業

ミニプログラムの開発入門については、WeChat Mini Programドキュメントをご参照ください。
Web美顔エフェクトSDKアクセスガイドをお読みになり、SDKの基本的な利用方法をご理解ください。

使用の開始

ステップ1:ミニプログラムバックエンド設定のドメイン名ホワイトリスト

SDK内部はバックエンドに認証とリソースロードをリクエストします。そのためミニプログラムを作成完了後に、ミニプラグラムのバックエンドでドメイン名ホワイトリストの設定が必要です。
1. ミニプログラムバックエンドを開き、開発 > 開発管理 > 開発設定 > サーバードメイン名に移動します。
2. 変更をクリックし、以下のドメイン名を設定の上、保存します。
リクエストドメイン名:
https://webar.qcloud.com;
https://webar-static.tencent-cloud.com;
https://aegis.qq.com;
および認証署名インターフェース(get-ar-sign)のアドレス
downloadFileドメイン名:
https://webar-static.tencent-cloud.com

ステップ2:npmのインストールと構築

ミニプログラムnpmについては、ミニプログラム使用のnpmをご参照ください。
1. インストール:
npm install tencentcloud-webar
2. 構築: ミニプログラム開発者ツールを開き、上部のメニューでツール > npm構築を選択します。
3. app.jsonでworkersパスを設定:
"workers": "miniprogram_npm/tencentcloud-webar/worker"

ステップ3:ファイルの導入

// 0.3.0より前のバージョンについての参照方式(ファイル1件)
// import "../../miniprogram_npm/tencentcloud-webar/lib.js";
// 0.3.0およびそれより後のバージョンについての参照方法(ファイル2件+必要に応じて3dモジュールを初期化)
import '../../miniprogram_npm/tencentcloud-webar/lib.js';
import '../../miniprogram_npm/tencentcloud-webar/core.js';
// 必要に応じて3dプラグインを初期化します。3dが必要ない場合は、参照なしにすることができます。
import '../../miniprogram_npm/tencentcloud-webar/lib-3d.js';
import { plugin3d } from '../../miniprogram_npm/tencentcloud-webar/plugin-3d'
// ArSdkインポート
import { ArSdk } from "../../miniprogram_npm/tencentcloud-webar/index.js";
注意
ミニプログラムの単一ファイルには500kb以内という制限があります。そのためSDKは2つのjsファイルに分けて提供します。
0.3.0より後のバージョンでは、SDKに対してさらに進んだ分割を行い、新しく3Dサポートを追加しました。3Dモジュールについて必要に応じたロード方式を提供します。導入前には現在使用中のSDKのバージョン情報をご確認の上、対応する導入方式をご選択ください。

ステップ4:SDKの初期化

注意
ミニプログラムのSDK初期化前には、コンソールでのミニプログラムAPPIDの設定が必要です。クイックマスターをご参照ください。
ページ内にcameraタグを挿入してカメラを開き、cameraパラメータを設定する必要があります。パラメータ設定については、アクセスガイドをご参照ください。
ミニプログラムはgetOutputをサポートしていません。ご自身で1つの画面上のwebgl canvasを渡す場合、SDKは直接画面をこのcanvas上に出力します。
サンプルコードは次のとおりです。
// wxml
//カメラを開き、positionでカメラを非表示にします
<camera
device-position="{{'front'}}"
frame-size="large" flash="off" resolution="medium"
style="width: 750rpx; height: 134rpx;position:absolute;top:-9999px;"
/>
//sdkが処理済みの画面をリアルタイムでこのcanvas上に出力します
<canvas
type="webgl"
canvas-id="main-canvas"
id="main-canvas"
style="width: 750rpx; height: 1334rpx;">
</canvas>
//撮影はImageDataオブジェクトをこのcanvas上に描画します
<canvas
type="2d"
canvas-id="photo-canvas"
id="photo-canvas"
style="position:absolute;width:720px;height:1280px;top:-9999px;left:-9999px;">
</canvas>
// js
/** ----- 認証設定 ----- */

/**
* Tencent CloudアカウントAPPID
*
* [Tencent Cloudアカウントセンター](https://console.cloud.tencent.com/developer) に移動すると、APPIDの確認ができます。
*/
const APPID = ''; // ここにご自身のパラメータを入力してください

/**
* Web LicenseKey
*
* オーディオビデオ端末SDKコンソールの[Web License管理](https://console.cloud.tencent.com/vcube/web)にログインし、プロジェクトを作成するとLicenseKeyが取得できます
*/
const LICENSE_KEY = ''; // ここにご自身のパラメータを入力してください

/**
* 署名用のキーTokenを計算します
*
* 注意:ここではDEMOデバッグのみでの使用となります。正式环境ではTokenをサーバーに保管してください。署名方法はサーバー側に移行することで実現します。インターフェースからの提供です。フロントエンド呼び出しで署名を取得します。
* [署名方法](https://cloud.tencent.com/document/product/616/71370#.E7.AD.BE.E5.90.8D.E6.96.B9.E6.B3.95)をご参照ください
*/
const token = ''; //ここにご自身のパラメータを入力してください

Component({
data: {
makeupList: [],
stickerList: [],
filterList: [],
recording: false
},
methods: {
async getCanvasNode(id) {
return new Promise((resolve) => {
this.createSelectorQuery()
.select(`#${id}`)
.node()
.exec((res) => {
const canvasNode = res[0].node;
resolve(canvasNode);
});
});
},
getSignature() {
const timestamp = Math.round(new Date().getTime() / 1000);
const signature = sha256(timestamp + token + APPID + timestamp).toUpperCase();
return { signature, timestamp };
},
//カメラ初期化のタイプ
async initSdkCamera() {
// 画面上のcanvasを取得すると、sdkが処理済み画面をリアルタイムでcanvas上に出力します
const outputCanvas = await this.getCanvasNode("main-canvas");
// 認証パラメータの取得
const auth = {
licenseKey: LICENSE_KEY,
appId: APP_ID,
authFunc: this.getSignature
};
// SDK初期化パラメータの作成
const config = {
auth,
camera: {
width:720,
height:1280,
},
output: outputCanvas,
// 美顔効果の初期化(オプション)
beautify: {
whiten: 0.1, // 美白 0-1
dermabrasion: 0.3, // 美肌 0-1
lift: 0, // 顔を細くする 0-1
shave: 0, // 顎を細くする 0-1
eye: 0.2, // 目を大きくする 0-1
chin: 0, // 下あご 0-1
}
};
const ar = new ArSdk(config);
// createdコールバックの中で内蔵エフェクトとフィルターリストの取得を開始できます
ar.on('created', () => {
// 内蔵コスメ、ステッカーリストの取得
ar.getEffectList({
Type: 'Preset'
}).then((res) => {
const list = res.map(item => ({
name: item.Name,
id: item.EffectId,
cover: item.CoverUrl,
url: item.Url,
label: item.Label,
type: item.PresetType,
}));
const makeupList = list.filter(item=>item.label.indexOf('美妆')>=0)
const stickerList = list.filter(item=>item.label.indexOf('贴纸')>=0)
// エフェクトリストのレンダリング
this.setData({
makeupList,
stickerList
});
}).catch((e) => {
console.log(e);
});
// 内蔵フィルター
ar.getCommonFilter().then((res) => {
const list = res.map(item => ({
name: item.Name,
id: item.EffectId,
cover: item.CoverUrl,
url: item.Url,
label: item.Label,
type: item.PresetType,
}));
// フィルターリストのレンダリング
this.setData({
filterList: list
});
}).catch((e) => {
console.log(e);
});
});
// readyコールバックの中で美顔、フィルター、特殊効果の設定ができます
ar.on('ready', (e) => {
this._sdkReady = true
});

ar.on('error', (e) => {
console.log(e);
});

this.ar = ar
},
// 美顔パラメータの変更、sdk readyの確保が必要です
onChangeBeauty(val){
if(!this._sdkReady) return
// setBeautifyによる美顔効果の設定で、6つの属性をサポートできます。詳しくはSDKアクセスガイドをご参照ください
this.ar.setBeautify({
dermabrasion: val.dermabrasion, // 美肌 0-1
});
},
// コスメの変更、sdk readyの確保が必要です
onChangeMakeup(id, intensity){
if(!this._sdkReady) return
// setEffectを利用してエフェクトを設定します。setEffectの入力パラメータは3種類の形式をサポートします。詳しくはSDKアクセスガイドをご参照ください
this.ar.setEffect([{id, intensity}]);
},
// ステッカーの変更、sdk readyの確保が必要です
onChangeSticker(id, intensity){
if(!this._sdkReady) return
// setEffectを利用してエフェクトを設定します。setEffectの入力パラメータは3種類の形式をサポートします。詳しくはSDKアクセスガイドをご参照ください
this.ar.setEffect([{id, intensity}]);
},
// フィルターの変更、sdk readyの確保が必要です
onChangeFilter(id, intensity){
if(!this._sdkReady) return
// setFilterを利用してフィルターを設定します。2つめのパラメータはフィルターの強度を表します(範囲0~1)
this.ar.setFilter(id, 1);
}
}
})

ステップ5:撮影および録画機能の実現

サンプルコードは次のとおりです。
撮影
録画
SDKは幅と高さおよびbufferデータを含むオブジェクトを返します。ユーザーはご自身のページ内にプリセットした2d canvas(上記コード中のidはphoto-canvas)でこのデータを描画し、画像ファイルとしてエクスポートできます。
async takePhoto() {
const {uint8ArrayData, width, height} = this.ar.takePhoto(); // takePhotoで現在の画面のbufferデータを返します
const photoCanvasNode = await this.getCanvasNode('photo-canvas');
photoCanvasNode.width = parseInt(width);
photoCanvasNode.height = parseInt(height);
const ctx = photoCanvasNode.getContext('2d');
// sdkが返したデータでImageDataオブジェクトを作成します
const imageData = photoCanvasNode.createImageData(uint8ArrayData, width, height);
// ImageDataオブジェクトをcanvas上に描画します
ctx.putImageData(imageData,0,0,0,0,width,height);
// canvasをローカル画像として保存します
wx.canvasToTempFilePath({
canvas: photoCanvasNode,
x: 0,
y: 0,
width: width,
height: height,
destWidth: width,
destHeight: height,
success: (res) => {
// 写真をローカルに保存します
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath
});
}
})
}
Component({
methods: {
// 録画の開始
startRecord() {
this.setData({
recording: true
});
this.ar.startRecord()
}
// 録画を終了
async stopRecord() {
const res = await this.ar.stopRecord();
// 録画をローカルに保存します
wx.saveVideoToPhotosAlbum({
filePath: res.tempFilePath
});
this.setData({
recording: false
});
}
}
})
ミニプログラムがバックエンドに切り替わった場合、あるいはスマホの画面ロックが確認された場合には、stopRecordを呼び出して録画を停止する必要があります。もう一度ページに戻る場合は、SDKを再度起動してください。
onShow() {
this.ar && this.ar.start();
},
onHide() {
this.ar && this.ar.stop();
},
async onUnload() {
try {
this.ar && this.ar.stop();
if (this.data.recording) {
await this.ar.stopRecord({
destroy: true,
});
}
} catch (e) {
}
this.ar && this.ar.destroy();
}

サンプルコード

サンプルコード をダウンロードし、解凍してからar-miniprogramコードの目次を確認することができます。