Kürzlich sollte eine WeChat-Passwortfunktion für rote Umschläge eingeführt werden. Er sagte, dass die Wollparty jetzt so weit verbreitet sei, dass der 100.000-Werbeumschlag in zwei Teilen aufgebraucht sei Tage? ... Können wir dann eine Funktion erstellen, um zu überprüfen, ob dieselbe Person den roten Umschlag erhält?
Der spezifische Prozess ist wie folgt:
Registrierte Voiceprint-Benutzer (endgültige Darstellung)
Voiceprint-Anmeldung (endgültige Darstellung)
Identifikation der Upload-Datei:
PM2-Thread
Da der Spracherkennungsdienstanbieter den Client nicht direkt für Anrufe verwenden kann und Audio nicht unterstützt wird, muss für die Verbindung ein eigener Server entwickelt werden.
Technologie-Stack koa + co-wecaht-api + mysql + ffmpeg + pm2 + knex
Hinweis: Da der Dienstanbieter keine WeChat-AMR-Dateien unterstützt, müssen Sie ffmpeg verwenden, um die WeChat-Audio-AMR-Dateien in WAV zu transkodieren.
Das Folgende ist ein relevanter Code, offen. .
WeChat jssdk-Entwicklung Wenn Sie bereits mit der WeChat-API vertraut sind, fahren Sie mit dem nächsten Abschnitt fort
Holen Sie sich ein WeChat-Token
var api = await new WechatAPI (
config . appid ,
config . appsecret ,
async ( ) => {
// 传入一个获取全局token的方法
var txt = await fs . readFile ( "./token/access_token.txt" , "utf8" ) ;
return JSON . parse ( txt ) ;
} ,
async token => {
// 请将token存储到全局,跨进程、跨机器级别的全局,比如写到数据库、redis等
// 这样才能在cluster模式及多机情况下使用,以下为写入到文件的示例
await fs . writeFile ( "./token/access_token.txt" , JSON . stringify ( token ) ) ;
}
) ;
Hinweis: Wenn die Token-Datei nicht gelesen werden kann, erstellen Sie manuell eine neue Textdatei im entsprechenden Verzeichnis, z. B. access_token.txt
Holen Sie sich die WeChat-Signatur
var jsapi_ticket = await api . getLatestTicket ( ) ;
let nonce_str = 'abcdefg' ; // 密钥,字符串任意,可以随机生成
let timestamp = parseInt ( new Date ( ) . getTime ( ) / 1000 ) + '' ; // 时间戳
let url = ctx . request . body . url ; // 使用接口的url链接,不包含#后的内容
let str = 'jsapi_ticket=' + jsapi_ticket . ticket + '&noncestr=' + nonce_str + '×tamp=' + timestamp + '&url=' + url ;
let signature = sha1 ( str ) ;
ctx . body = {
appId : config . appid ,
timestamp : timestamp ,
nonceStr : nonce_str ,
signature : signature
}
domänenübergreifende Anfrage
const Koa = require ( "koa" ) ;
const app = new Koa ( ) ;
const cors = require ( "koa-cors" ) ;
... . .
app . use (
cors ( {
origin : "http://www.xxxx.com" ,
maxAge : 5 ,
credentials : true ,
allowMethods : [ "OPTIONS" , "GET" , "POST" , "DELETE" ] ,
allowHeaders : [ 'Content-Type' , 'Accept' ]
} )
) ;
ffmpeg-Transkodierung
const ffmpeg = require ( 'fluent-ffmpeg' ) ;
... .
var command = ffmpeg ( _delPath . amr )
. audioBitrate ( '16k' ) //16k音频采样率
. audioFrequency ( 16000 ) //16比特音频信号
. audioQuality ( 10 ) //音频质量
. on ( 'end' , function ( ) {
console . log ( 'file has been converted succesfully' ) ;
resolve ( ) ;
} )
. on ( 'error' , function ( err ) {
reject ( err . message )
console . log ( 'an error happened: ' + err . message ) ;
} )
. save ( _delPath . fix ) ;
Senden Sie den Voiceprint-Server
const rp = require ( "request-promise" ) ;
... . .
var vprData = {
method : "POST" ,
url : "http://www.xxxx.com" ,
headers : {
"cache-control" : "no-cache" ,
"x-udid" : "xxxxxx" ,
"x-session-key" : "xxxx" ,
"x-task-config" : "xxxxxx" ,
"x-request-date" : "xxxxxx" ,
"x-sdk-version" : "5.1" ,
"x-app-key" : "xxxxxxx"
} ,
formData : {
// Like <input type="file" name="file">
file : {
value : fs . createReadStream ( soundData . path ) ,
options : {
filename : soundData . name ,
contentType : soundData . type //mp3 = audio/mpeg, wav = audio/wav
}
}
}
} ;
var xml = await rp ( vprData ) ;
//xml to json
var resJson = { } ;
var parseString = require ( 'xml2js' ) . parseString ;
await new Promise ( ( resolve , reject ) => {
parseString ( xml . toString ( ) , async ( err , result ) => {
resJson = result . ResponseInfo ;
//do something
resolve ( ) ;
} ) ;
} ) ;
Technologie-Stack Vue + Vue-Router + Axios.
Entfernen Sie die Popup-Kopierschaltfläche durch langes Drücken auf WeChat
mounted ( ) {
document . oncontextmenu = function ( e ) {
e . preventDefault ( ) ;
} ;
//初始化 微信jssdk
vm . wx_init ( ) ;
}
Holen Sie sich eine WeChat-Signatur und registrieren Sie sich für die Veranstaltung
wx . config ( {
debug : false , // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId : res . appId , // 必填,公众号的唯一标识
timestamp : res . timestamp , // 必填,生成签名的时间戳
nonceStr : res . nonceStr , // 必填,生成签名的随机串
signature : res . signature , // 必填,签名,见附录1
jsApiList : [
"onMenuShareTimeline" ,
"onMenuShareAppMessage" ,
"uploadVoice" ,
"startRecord" ,
"playVoice" ,
"stopRecord" ,
"onVoicePlayEnd"
] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
} ) ;
Fordern Sie den Benutzer im Voraus auf, die Aufnahmefunktion zu autorisieren, um zu vermeiden, dass er gleichzeitig zur Autorisierung aufgefordert wird, wenn die Aufnahme offiziell gestartet wird. Zu diesem Zeitpunkt ist der Status der Aufnahmefunktion außer Kontrolle.
if ( ! localStorage . rainAllowRecord || localStorage . rainAllowRecord !== "true" ) {
wx . startRecord ( {
success : function ( ) {
localStorage . rainAllowRecord = "true" ;
wx . stopRecord ( ) ;
} ,
cancel : function ( ) {
alert ( "用户拒绝授权录音" ) ;
}
} ) ;
}
Okay, reden ist billig, zeig dir den Code.
Wie zu verwenden
git clone https: //github.com/ssttm169/tom-vpr.git
cd server
npm i / yarn
npm run dev //本地开发
npm start //服务器跑
//或者
cd client
npm i / yarn
npm run dev //本地开发
npm start //服务上跑客户端