"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QiniuCloudInstance = void 0; const tslib_1 = require("tslib"); require('../../fetch'); const crypto_1 = tslib_1.__importDefault(require("crypto")); const ts_md5_1 = require("ts-md5"); const buffer_1 = require("buffer"); class QiniuCloudInstance { accessKey; secretKey; constructor(accessKey, secretKey) { this.accessKey = accessKey; this.secretKey = secretKey; } /** * 计算客户端上传七牛需要的凭证 * https://developer.qiniu.com/kodo/1312/upload * @param uploadHost * @param bucket * @param key * @returns */ getUploadInfo(uploadHost, bucket, key) { try { const scope = key ? `${bucket}:${key}` : bucket; const uploadToken = this.getToken(scope); return { key, uploadToken, uploadHost, bucket, }; } catch (err) { throw err; } } /** * 计算直播需要的token * @param method * @param path * @param host * @param rawQuery * @param contentType * @param bodyStr * @returns */ getLiveToken(method, path, host, rawQuery, contentType, bodyStr) { // 1. 添加 Path let data = `${method} ${path}`; if (rawQuery) { data += `?${rawQuery}`; } data += `\nHost: ${host}`; if (contentType) { data += `\nContent-Type: ${contentType}`; } data += '\n\n'; if (bodyStr && contentType && contentType !== 'application/octet-stream') { data += bodyStr; } const sign = this.hmacSha1(data, this.secretKey); const encodedSign = this.base64ToUrlSafe(sign); const toke = 'Qiniu ' + this.accessKey + ':' + encodedSign; return toke; } async getLiveStream(hub, method, streamTitle, host, publishDomain, playDomain, publishKey, playKey, expireAt) { // 七牛创建直播流接口路径 const path = `/v2/hubs/${hub}/streams`; // 如果用户没给streamTitle,那么随机生成一个 let key = streamTitle; if (!key) { key = `class${new Date().getTime()}`; } const bodyStr = JSON.stringify({ key, }); const contentType = 'application/json'; const token = this.getLiveToken(method, path, host); const url = `https://pili.qiniuapi.com/v2/hubs/${hub}/streams`; await global.fetch(url, { method: 'POST', headers: { Authorization: token, 'Content-Type': contentType, }, body: bodyStr, mode: 'no-cors', }); const obj = this.getStreamObj(publishDomain, playDomain, hub, publishKey, playKey, streamTitle, expireAt); return obj; } /** * 计算直播流地址相关信息 * @param publishDomain * @param playDomain * @param hub * @param publishKey * @param playKey * @param streamTitle * @param expireAt * @returns */ getStreamObj(publishDomain, playDomain, hub, publishKey, playKey, streamTitle, expireAt) { const signStr = `/${hub}/${streamTitle}?expire=${expireAt}`; const sourcePath = `/${hub}/${streamTitle}`; const token = this.base64ToUrlSafe(this.hmacSha1(signStr, publishKey)); const rtmpPushUrl = `rtmp://${publishDomain}${signStr}&token=${token}`; // 生成播放地址 const t = expireAt.toString(16).toLowerCase(); const playSign = ts_md5_1.Md5.hashStr(playKey + sourcePath + t) .toString() .toLowerCase(); const rtmpPlayUrl = `https://${playDomain}${sourcePath}.m3u8?sign=${playSign}&t=${t}`; // obs推流需要的地址和串流密钥 const pcPushUrl = `rtmp://${publishDomain}/${hub}/`; const streamKey = `${streamTitle}?expire=${expireAt}&token=${token}`; return { streamTitle, hub, rtmpPushUrl, rtmpPlayUrl, pcPushUrl, streamKey, expireAt, }; } async getPlayBackUrl(hub, playBackDomain, streamTitle, start, end, method, host, rawQuery) { const encodeStreamTitle = this.base64ToUrlSafe(streamTitle); const path = `/v2/hubs/${hub}/streams/${encodeStreamTitle}/saveas`; const bodyStr = JSON.stringify({ fname: streamTitle, start, end, }); const contentType = 'application/json'; const token = this.getLiveToken(method, path, host, rawQuery, contentType, bodyStr); const url = `https://pili.qiniuapi.com${path}`; await global.fetch(url, { method: 'POST', headers: { Authorization: token, 'Content-Type': contentType, }, body: bodyStr, mode: 'no-cors', }); return `https://${playBackDomain}/${streamTitle}.m3u8`; } getToken(scope) { // 构造策略 const putPolicy = { scope: scope, deadline: 3600 + Math.floor(Date.now() / 1000), }; // 构造凭证 const encodedFlags = this.urlSafeBase64Encode(JSON.stringify(putPolicy)); const encoded = this.hmacSha1(encodedFlags, this.secretKey); const encodedSign = this.base64ToUrlSafe(encoded); const uploadToken = this.accessKey + ':' + encodedSign + ':' + encodedFlags; return uploadToken; } base64ToUrlSafe(v) { return v.replace(/\//g, '_').replace(/\+/g, '-'); } hmacSha1(encodedFlags, secretKey) { const hmac = crypto_1.default.createHmac('sha1', secretKey); hmac.update(encodedFlags); return hmac.digest('base64'); } urlSafeBase64Encode(jsonFlags) { const encoded = buffer_1.Buffer.from(jsonFlags).toString('base64'); return this.base64ToUrlSafe(encoded); } } exports.QiniuCloudInstance = QiniuCloudInstance;