@besovideo/webrtc-player 0.8.95 → 0.8.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -171,9 +171,49 @@ instance.playerStatus : {
171
171
  // 设置录像状态
172
172
  Set(status: {type: "recordStart" | "recordStop"}): void;
173
173
  // 添加事件监听, type == "recordStop" recordInfo 才有值
174
- addEventListener(handle: ((status: {type: "recordStart" | "recordStop", recordInfo?: { data: Blob, cancelAutoDownload: () => void} }) => void)):void;
174
+ addEventListener(handle: ((status: {
175
+ type: "recordStart" | "recordStop",
176
+ recordInfo?: {
177
+ data: Blob; // 数据
178
+ startTime: number; // 录像开始时间 utc ms
179
+ endTime: number; // 录像结束时间 utc ms
180
+ duration: number; // 录像时长 ms
181
+ fileName: string; // 文件名
182
+ puOptions: {
183
+ id: string; // 设备名称
184
+ index: number; // 通道ID
185
+ name?: string; //设备名称,用于内部UI显示
186
+ indexName?: string; //通道名称,用于内部UI显示
187
+ },
188
+ //调用将取消自动下载,返回下载函数
189
+ cancelAutoDownload: () => {
190
+ //调用该接口,浏览器下载文件, filename 不填为默认的文件名,否则为[filename].webm
191
+ download(filename?: string): void;
192
+ }
193
+ }
194
+ }) => void)):void;
175
195
  // 移除事件监听
176
- removeEventListener(handle: ((status: {type: "recordStart" | "recordStop", recordInfo?: {data: Blob, cancelAutoDownload: () => void} }) => void)):void;
196
+ removeEventListener(handle: ((status: {
197
+ type: "recordStart" | "recordStop",
198
+ recordInfo?: {
199
+ data: Blob; // 数据
200
+ startTime: number; // 录像开始时间 utc ms
201
+ endTime: number; // 录像结束时间 utc ms
202
+ duration: number; // 录像时长 ms
203
+ fileName: string; // 文件名
204
+ puOptions: {
205
+ id: string; // 设备名称
206
+ index: number; // 通道ID
207
+ name?: string; //设备名称,用于内部UI显示
208
+ indexName?: string; //通道名称,用于内部UI显示
209
+ },
210
+ //调用将取消自动下载,返回下载函数
211
+ cancelAutoDownload: () => {
212
+ //调用该接口,浏览器下载文件, filename 不填为默认的文件名,否则为[filename].webm
213
+ download(filename?: string): void;
214
+ }
215
+ }
216
+ }) => void)):void;
177
217
  },
178
218
  rotate: {
179
219
  // 获取旋转状态,顺时针方向
@@ -117,7 +117,7 @@ var bvPlayerCore = (() => {
117
117
  var define_processenv_default;
118
118
  var init_define_processenv = __esm({
119
119
  "<define:processenv>"() {
120
- define_processenv_default = { NODE_ENV: "production", SH_LIB_NAME: "@besovideo/webrtc-player", SH_LIB_VERSION: "0.8.95", PROJECT_NAMESPACE: "bvplayer" };
120
+ define_processenv_default = { NODE_ENV: "production", SH_LIB_NAME: "@besovideo/webrtc-player", SH_LIB_VERSION: "0.8.96", PROJECT_NAMESPACE: "bvplayer" };
121
121
  }
122
122
  });
123
123
 
@@ -7125,6 +7125,7 @@ If you want to allow non-zero first timestamps, set firstTimestampBehavior: 'per
7125
7125
  description: audioCodecPrivate
7126
7126
  }
7127
7127
  } : void 0;
7128
+ let maxTimestamp = -1;
7128
7129
  handleEle((timestamp, data, bVideo, bKeyFrame) => {
7129
7130
  if (bVideo) {
7130
7131
  muxer.addVideoChunkRaw(data, bKeyFrame ? "key" : "delta", timestamp);
@@ -7133,9 +7134,15 @@ If you want to allow non-zero first timestamps, set firstTimestampBehavior: 'per
7133
7134
  muxer.addAudioChunkRaw(data, "key", timestamp, config);
7134
7135
  }
7135
7136
  }
7137
+ if (maxTimestamp < timestamp) {
7138
+ maxTimestamp = timestamp;
7139
+ }
7136
7140
  });
7137
7141
  muxer.finalize();
7138
- return new Blob([muxer.target.buffer]);
7142
+ return {
7143
+ blob: new Blob([muxer.target.buffer]),
7144
+ maxTimestamp
7145
+ };
7139
7146
  });
7140
7147
  }
7141
7148
  var createMediaRecorder = (mediaStream, done, mediaRecorderPartner) => {
@@ -7173,6 +7180,7 @@ If you want to allow non-zero first timestamps, set firstTimestampBehavior: 'per
7173
7180
  return mediaRecorder;
7174
7181
  };
7175
7182
  var createRecord = (_mediaStream, fileName, isDownload) => {
7183
+ const startTime = Date.now();
7176
7184
  const tempMediaStreams = _mediaStream.getTracks().map((item) => {
7177
7185
  const mediaStream2 = new MediaStream([item]);
7178
7186
  item.addEventListener("ended", () => {
@@ -7189,14 +7197,30 @@ If you want to allow non-zero first timestamps, set firstTimestampBehavior: 'per
7189
7197
  const szWebM = [];
7190
7198
  function done(e) {
7191
7199
  return __async(this, null, function* () {
7200
+ let maxTimestamp = -1;
7192
7201
  szWebM.push(e.data);
7193
7202
  if (szWebM.length == mediaStreams.length) {
7194
- recordedChunks.push(yield combinaWebM(...szWebM));
7203
+ const { blob: blobWebM, maxTimestamp: _maxTimestamp } = yield combinaWebM(
7204
+ ...szWebM
7205
+ );
7206
+ recordedChunks.push(blobWebM);
7207
+ if (_maxTimestamp > maxTimestamp) {
7208
+ maxTimestamp = _maxTimestamp;
7209
+ }
7195
7210
  const blob = new Blob(recordedChunks, {
7196
7211
  type: "video/webm"
7197
7212
  });
7198
- if (yield isDownload(blob)) {
7199
- file_default.downLoadBlob(blob, fileName, "webm");
7213
+ const downloadFile = (inFileName) => {
7214
+ file_default.downLoadBlob(blob, inFileName ? inFileName : fileName, "webm");
7215
+ };
7216
+ if (isDownload(blob, { duration: maxTimestamp / 1e3, startTime, endTime: startTime + maxTimestamp / 1e3, fileName }, () => {
7217
+ return {
7218
+ download(file2) {
7219
+ downloadFile(file2);
7220
+ }
7221
+ };
7222
+ })) {
7223
+ downloadFile(fileName);
7200
7224
  }
7201
7225
  recordedChunks = [];
7202
7226
  }
@@ -7250,19 +7274,28 @@ If you want to allow non-zero first timestamps, set firstTimestampBehavior: 'per
7250
7274
  try {
7251
7275
  const mediaStream = stream || element.captureStream(25);
7252
7276
  let gOnMediaHolder = void 0;
7253
- const mediaRecorder = createRecord(mediaStream, fileName, (blob) => __async(void 0, null, function* () {
7254
- if (gOnMediaHolder) {
7255
- const holder = gOnMediaHolder;
7256
- gOnMediaHolder = void 0;
7257
- let bDownload = true;
7258
- const cancelAutoDownload = () => {
7259
- bDownload = false;
7260
- };
7261
- yield holder(blob, cancelAutoDownload);
7262
- return bDownload;
7277
+ const mediaRecorder = createRecord(
7278
+ mediaStream,
7279
+ fileName,
7280
+ (blob, metaInfo, downloadRecordGetter) => {
7281
+ if (gOnMediaHolder) {
7282
+ const holder = gOnMediaHolder;
7283
+ gOnMediaHolder = void 0;
7284
+ let bDownload = true;
7285
+ const cancelAutoDownload = () => {
7286
+ bDownload = false;
7287
+ return downloadRecordGetter();
7288
+ };
7289
+ holder(
7290
+ blob,
7291
+ metaInfo,
7292
+ cancelAutoDownload
7293
+ );
7294
+ return bDownload;
7295
+ }
7296
+ return true;
7263
7297
  }
7264
- return true;
7265
- }));
7298
+ );
7266
7299
  logger_default.info("\u5F55\u5236\u5B9E\u4F8B", mediaRecorder);
7267
7300
  return [
7268
7301
  mediaRecorder,
@@ -12914,6 +12947,7 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
12914
12947
  this._video = new video_default({
12915
12948
  puOptions: options == null ? void 0 : options.puOptions
12916
12949
  });
12950
+ this._puOptions = options == null ? void 0 : options.puOptions;
12917
12951
  this._spinner = new spinner_default({ spin: false });
12918
12952
  this._toast = new toast_default();
12919
12953
  this._mask = new mask_default({ visible: false });
@@ -13189,12 +13223,15 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
13189
13223
  if ((_a = this._panel) == null ? void 0 : _a.controller.RecordButton) {
13190
13224
  (_b = this._panel) == null ? void 0 : _b.controller.RecordButton.dispatch("click");
13191
13225
  } else {
13192
- this._video.recordStop((blob, cancelAutoDownload) => {
13193
- this.dispatch("recordStop", {
13226
+ this._video.recordStop((blob, mataInfo, cancelAutoDownload) => {
13227
+ this.dispatch("recordStop", __spreadProps(__spreadValues({
13228
+ puOptions: this._puOptions
13229
+ }, mataInfo), {
13194
13230
  data: blob,
13195
13231
  cancelAutoDownload
13196
- });
13232
+ }));
13197
13233
  this._recordState.dispatch("RecordEnd");
13234
+ return false;
13198
13235
  });
13199
13236
  }
13200
13237
  }
@@ -13260,12 +13297,15 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
13260
13297
  this._recordState.dispatch("RecordStart");
13261
13298
  });
13262
13299
  panel.controller.addEventListener("recordStop", () => {
13263
- this._video.recordStop((blob, cancelAutoDownload) => {
13264
- this.dispatch("recordStop", {
13300
+ this._video.recordStop((blob, metaInfo, cancelAutoDownload) => {
13301
+ this.dispatch("recordStop", __spreadProps(__spreadValues({
13302
+ puOptions: this._puOptions
13303
+ }, metaInfo), {
13265
13304
  data: blob,
13266
13305
  cancelAutoDownload
13267
- });
13306
+ }));
13268
13307
  this._recordState.dispatch("RecordEnd");
13308
+ return false;
13269
13309
  });
13270
13310
  });
13271
13311
  panel.controller.addEventListener("rotate", () => {
@@ -13573,6 +13613,7 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
13573
13613
  // smooth: 播放平滑度。[1,7],值越小越实时。
13574
13614
  // algokey: 加解密算法:密钥。格式:算法:base64(密钥)。例如: SM4:MTIzNDU2Nzg=
13575
13615
  constructor() {
13616
+ console.log("================== bvrtc version: 1.0.1 20241028 ==================");
13576
13617
  this.hplayer = 0;
13577
13618
  this.canvas = null;
13578
13619
  this.dialogid = "";
@@ -14501,6 +14542,20 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
14501
14542
  this.audioCtx.close();
14502
14543
  this.audioCtx = null;
14503
14544
  };
14545
+ var woker_str = `
14546
+ class BVAudioProcessor extends AudioWorkletProcessor {
14547
+ process(inputs, outputs, parameters) {
14548
+ const inputdata = inputs[0][0];
14549
+ this.port.postMessage(inputdata);
14550
+ return true;
14551
+ }
14552
+ }
14553
+ registerProcessor('bv-audio-processor', BVAudioProcessor);
14554
+ `;
14555
+ var audioProcessorBolb = new Blob([woker_str], {
14556
+ type: "application/javascript"
14557
+ });
14558
+ var audioProcessorUrl = URL.createObjectURL(audioProcessorBolb);
14504
14559
  function BVPcmRecorder(config, cb) {
14505
14560
  if (!config) {
14506
14561
  config = {
@@ -14512,7 +14567,7 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
14512
14567
  };
14513
14568
  }
14514
14569
  this.config = config;
14515
- this.sampleRate = new (window.AudioContext || window.webkitAudioContext)().sampleRate;
14570
+ this.sampleRate = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: this.config.sampleRate }).sampleRate;
14516
14571
  this.fftSize = 512;
14517
14572
  this.analyser = null;
14518
14573
  this.audioInput = null;
@@ -14522,20 +14577,23 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
14522
14577
  this.audioData = null;
14523
14578
  this.audioSize = 0;
14524
14579
  this.cb = cb;
14525
- this.init();
14526
14580
  console.log("sampleRate " + this.sampleRate);
14527
14581
  }
14528
14582
  BVPcmRecorder.prototype.start = function() {
14529
- navigator.mediaDevices.getUserMedia({
14530
- audio: true
14531
- }).then((stream) => {
14532
- this.audioInput = this.context.createMediaStreamSource(stream);
14533
- }, (error2) => {
14534
- console.error(error2);
14535
- }).then(() => {
14536
- this.audioInput.connect(this.analyser);
14537
- this.analyser.connect(this.recorder);
14538
- this.recorder.connect(this.context.destination);
14583
+ return __async(this, null, function* () {
14584
+ yield this.init();
14585
+ navigator.mediaDevices.getUserMedia({
14586
+ audio: true,
14587
+ sampleRate: this.config.sampleRate
14588
+ }).then((stream) => {
14589
+ this.audioInput = this.context.createMediaStreamSource(stream);
14590
+ }, (error2) => {
14591
+ console.error(error2);
14592
+ }).then(() => {
14593
+ this.audioInput.connect(this.analyser);
14594
+ this.analyser.connect(this.recorder);
14595
+ this.recorder.connect(this.context.destination);
14596
+ });
14539
14597
  });
14540
14598
  };
14541
14599
  BVPcmRecorder.prototype.stop = function() {
@@ -14543,23 +14601,21 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
14543
14601
  this.audioInput.disconnect();
14544
14602
  if (this.recorder)
14545
14603
  this.recorder.disconnect();
14604
+ if (this.context)
14605
+ this.context.close();
14546
14606
  };
14547
14607
  BVPcmRecorder.prototype.init = function() {
14548
- this.context = new (window.AudioContext || window.webkitAudioContext)();
14549
- this.analyser = this.context.createAnalyser();
14550
- this.analyser.fftSize = this.fftSize;
14551
- const createScript = this.context.createScriptProcessor || this.context.createJavaScriptNode;
14552
- this.recorder = createScript.apply(
14553
- this.context,
14554
- [this.fftSize, this.config.numberChannels, this.config.numberChannels]
14555
- );
14556
- this.recorder.onaudioprocess = this.onaudioprocess.bind(this);
14557
- };
14558
- BVPcmRecorder.prototype.onaudioprocess = function(e) {
14559
- if (this.config.numberChannels === 1) {
14560
- const data = e.inputBuffer.getChannelData(0);
14561
- this.handlePcm(new Float32Array(data));
14562
- }
14608
+ return __async(this, null, function* () {
14609
+ this.context = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: this.config.sampleRate });
14610
+ this.analyser = this.context.createAnalyser();
14611
+ this.analyser.fftSize = this.fftSize;
14612
+ yield this.context.audioWorklet.addModule(audioProcessorUrl);
14613
+ this.recorder = new AudioWorkletNode(this.context, "bv-audio-processor");
14614
+ this.recorder.port.onmessage = (e) => {
14615
+ if (e.data)
14616
+ this.handlePcm(e.data);
14617
+ };
14618
+ });
14563
14619
  };
14564
14620
  BVPcmRecorder.prototype.handlePcm = function(bytes) {
14565
14621
  if (bytes[0] === 0 && bytes[1] === 0)
package/dist/main.es.js CHANGED
@@ -111,7 +111,7 @@ var __async = (__this, __arguments, generator) => {
111
111
  var define_processenv_default;
112
112
  var init_define_processenv = __esm({
113
113
  "<define:processenv>"() {
114
- define_processenv_default = { NODE_ENV: "production", SH_LIB_NAME: "@besovideo/webrtc-player", SH_LIB_VERSION: "0.8.95", PROJECT_NAMESPACE: "bvplayer" };
114
+ define_processenv_default = { NODE_ENV: "production", SH_LIB_NAME: "@besovideo/webrtc-player", SH_LIB_VERSION: "0.8.96", PROJECT_NAMESPACE: "bvplayer" };
115
115
  }
116
116
  });
117
117
 
@@ -7109,6 +7109,7 @@ function combinaWebM(webM1, webM2) {
7109
7109
  description: audioCodecPrivate
7110
7110
  }
7111
7111
  } : void 0;
7112
+ let maxTimestamp = -1;
7112
7113
  handleEle((timestamp, data, bVideo, bKeyFrame) => {
7113
7114
  if (bVideo) {
7114
7115
  muxer.addVideoChunkRaw(data, bKeyFrame ? "key" : "delta", timestamp);
@@ -7117,9 +7118,15 @@ function combinaWebM(webM1, webM2) {
7117
7118
  muxer.addAudioChunkRaw(data, "key", timestamp, config);
7118
7119
  }
7119
7120
  }
7121
+ if (maxTimestamp < timestamp) {
7122
+ maxTimestamp = timestamp;
7123
+ }
7120
7124
  });
7121
7125
  muxer.finalize();
7122
- return new Blob([muxer.target.buffer]);
7126
+ return {
7127
+ blob: new Blob([muxer.target.buffer]),
7128
+ maxTimestamp
7129
+ };
7123
7130
  });
7124
7131
  }
7125
7132
  var createMediaRecorder = (mediaStream, done, mediaRecorderPartner) => {
@@ -7157,6 +7164,7 @@ var createMediaRecorder = (mediaStream, done, mediaRecorderPartner) => {
7157
7164
  return mediaRecorder;
7158
7165
  };
7159
7166
  var createRecord = (_mediaStream, fileName, isDownload) => {
7167
+ const startTime = Date.now();
7160
7168
  const tempMediaStreams = _mediaStream.getTracks().map((item) => {
7161
7169
  const mediaStream2 = new MediaStream([item]);
7162
7170
  item.addEventListener("ended", () => {
@@ -7173,14 +7181,30 @@ var createRecord = (_mediaStream, fileName, isDownload) => {
7173
7181
  const szWebM = [];
7174
7182
  function done(e) {
7175
7183
  return __async(this, null, function* () {
7184
+ let maxTimestamp = -1;
7176
7185
  szWebM.push(e.data);
7177
7186
  if (szWebM.length == mediaStreams.length) {
7178
- recordedChunks.push(yield combinaWebM(...szWebM));
7187
+ const { blob: blobWebM, maxTimestamp: _maxTimestamp } = yield combinaWebM(
7188
+ ...szWebM
7189
+ );
7190
+ recordedChunks.push(blobWebM);
7191
+ if (_maxTimestamp > maxTimestamp) {
7192
+ maxTimestamp = _maxTimestamp;
7193
+ }
7179
7194
  const blob = new Blob(recordedChunks, {
7180
7195
  type: "video/webm"
7181
7196
  });
7182
- if (yield isDownload(blob)) {
7183
- file_default.downLoadBlob(blob, fileName, "webm");
7197
+ const downloadFile = (inFileName) => {
7198
+ file_default.downLoadBlob(blob, inFileName ? inFileName : fileName, "webm");
7199
+ };
7200
+ if (isDownload(blob, { duration: maxTimestamp / 1e3, startTime, endTime: startTime + maxTimestamp / 1e3, fileName }, () => {
7201
+ return {
7202
+ download(file2) {
7203
+ downloadFile(file2);
7204
+ }
7205
+ };
7206
+ })) {
7207
+ downloadFile(fileName);
7184
7208
  }
7185
7209
  recordedChunks = [];
7186
7210
  }
@@ -7234,19 +7258,28 @@ var record = (element, stream, fileName = `record_${Date.now()}`) => {
7234
7258
  try {
7235
7259
  const mediaStream = stream || element.captureStream(25);
7236
7260
  let gOnMediaHolder = void 0;
7237
- const mediaRecorder = createRecord(mediaStream, fileName, (blob) => __async(void 0, null, function* () {
7238
- if (gOnMediaHolder) {
7239
- const holder = gOnMediaHolder;
7240
- gOnMediaHolder = void 0;
7241
- let bDownload = true;
7242
- const cancelAutoDownload = () => {
7243
- bDownload = false;
7244
- };
7245
- yield holder(blob, cancelAutoDownload);
7246
- return bDownload;
7261
+ const mediaRecorder = createRecord(
7262
+ mediaStream,
7263
+ fileName,
7264
+ (blob, metaInfo, downloadRecordGetter) => {
7265
+ if (gOnMediaHolder) {
7266
+ const holder = gOnMediaHolder;
7267
+ gOnMediaHolder = void 0;
7268
+ let bDownload = true;
7269
+ const cancelAutoDownload = () => {
7270
+ bDownload = false;
7271
+ return downloadRecordGetter();
7272
+ };
7273
+ holder(
7274
+ blob,
7275
+ metaInfo,
7276
+ cancelAutoDownload
7277
+ );
7278
+ return bDownload;
7279
+ }
7280
+ return true;
7247
7281
  }
7248
- return true;
7249
- }));
7282
+ );
7250
7283
  logger_default.info("\u5F55\u5236\u5B9E\u4F8B", mediaRecorder);
7251
7284
  return [
7252
7285
  mediaRecorder,
@@ -12898,6 +12931,7 @@ var PlayerPlugin = class extends Plugin {
12898
12931
  this._video = new video_default({
12899
12932
  puOptions: options == null ? void 0 : options.puOptions
12900
12933
  });
12934
+ this._puOptions = options == null ? void 0 : options.puOptions;
12901
12935
  this._spinner = new spinner_default({ spin: false });
12902
12936
  this._toast = new toast_default();
12903
12937
  this._mask = new mask_default({ visible: false });
@@ -13173,12 +13207,15 @@ var PlayerPlugin = class extends Plugin {
13173
13207
  if ((_a = this._panel) == null ? void 0 : _a.controller.RecordButton) {
13174
13208
  (_b = this._panel) == null ? void 0 : _b.controller.RecordButton.dispatch("click");
13175
13209
  } else {
13176
- this._video.recordStop((blob, cancelAutoDownload) => {
13177
- this.dispatch("recordStop", {
13210
+ this._video.recordStop((blob, mataInfo, cancelAutoDownload) => {
13211
+ this.dispatch("recordStop", __spreadProps(__spreadValues({
13212
+ puOptions: this._puOptions
13213
+ }, mataInfo), {
13178
13214
  data: blob,
13179
13215
  cancelAutoDownload
13180
- });
13216
+ }));
13181
13217
  this._recordState.dispatch("RecordEnd");
13218
+ return false;
13182
13219
  });
13183
13220
  }
13184
13221
  }
@@ -13244,12 +13281,15 @@ var PlayerPlugin = class extends Plugin {
13244
13281
  this._recordState.dispatch("RecordStart");
13245
13282
  });
13246
13283
  panel.controller.addEventListener("recordStop", () => {
13247
- this._video.recordStop((blob, cancelAutoDownload) => {
13248
- this.dispatch("recordStop", {
13284
+ this._video.recordStop((blob, metaInfo, cancelAutoDownload) => {
13285
+ this.dispatch("recordStop", __spreadProps(__spreadValues({
13286
+ puOptions: this._puOptions
13287
+ }, metaInfo), {
13249
13288
  data: blob,
13250
13289
  cancelAutoDownload
13251
- });
13290
+ }));
13252
13291
  this._recordState.dispatch("RecordEnd");
13292
+ return false;
13253
13293
  });
13254
13294
  });
13255
13295
  panel.controller.addEventListener("rotate", () => {
@@ -13557,6 +13597,7 @@ var BVMedia = class {
13557
13597
  // smooth: 播放平滑度。[1,7],值越小越实时。
13558
13598
  // algokey: 加解密算法:密钥。格式:算法:base64(密钥)。例如: SM4:MTIzNDU2Nzg=
13559
13599
  constructor() {
13600
+ console.log("================== bvrtc version: 1.0.1 20241028 ==================");
13560
13601
  this.hplayer = 0;
13561
13602
  this.canvas = null;
13562
13603
  this.dialogid = "";
@@ -14485,6 +14526,20 @@ BVPCMPlayer.prototype.destroy = function() {
14485
14526
  this.audioCtx.close();
14486
14527
  this.audioCtx = null;
14487
14528
  };
14529
+ var woker_str = `
14530
+ class BVAudioProcessor extends AudioWorkletProcessor {
14531
+ process(inputs, outputs, parameters) {
14532
+ const inputdata = inputs[0][0];
14533
+ this.port.postMessage(inputdata);
14534
+ return true;
14535
+ }
14536
+ }
14537
+ registerProcessor('bv-audio-processor', BVAudioProcessor);
14538
+ `;
14539
+ var audioProcessorBolb = new Blob([woker_str], {
14540
+ type: "application/javascript"
14541
+ });
14542
+ var audioProcessorUrl = URL.createObjectURL(audioProcessorBolb);
14488
14543
  function BVPcmRecorder(config, cb) {
14489
14544
  if (!config) {
14490
14545
  config = {
@@ -14496,7 +14551,7 @@ function BVPcmRecorder(config, cb) {
14496
14551
  };
14497
14552
  }
14498
14553
  this.config = config;
14499
- this.sampleRate = new (window.AudioContext || window.webkitAudioContext)().sampleRate;
14554
+ this.sampleRate = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: this.config.sampleRate }).sampleRate;
14500
14555
  this.fftSize = 512;
14501
14556
  this.analyser = null;
14502
14557
  this.audioInput = null;
@@ -14506,20 +14561,23 @@ function BVPcmRecorder(config, cb) {
14506
14561
  this.audioData = null;
14507
14562
  this.audioSize = 0;
14508
14563
  this.cb = cb;
14509
- this.init();
14510
14564
  console.log("sampleRate " + this.sampleRate);
14511
14565
  }
14512
14566
  BVPcmRecorder.prototype.start = function() {
14513
- navigator.mediaDevices.getUserMedia({
14514
- audio: true
14515
- }).then((stream) => {
14516
- this.audioInput = this.context.createMediaStreamSource(stream);
14517
- }, (error2) => {
14518
- console.error(error2);
14519
- }).then(() => {
14520
- this.audioInput.connect(this.analyser);
14521
- this.analyser.connect(this.recorder);
14522
- this.recorder.connect(this.context.destination);
14567
+ return __async(this, null, function* () {
14568
+ yield this.init();
14569
+ navigator.mediaDevices.getUserMedia({
14570
+ audio: true,
14571
+ sampleRate: this.config.sampleRate
14572
+ }).then((stream) => {
14573
+ this.audioInput = this.context.createMediaStreamSource(stream);
14574
+ }, (error2) => {
14575
+ console.error(error2);
14576
+ }).then(() => {
14577
+ this.audioInput.connect(this.analyser);
14578
+ this.analyser.connect(this.recorder);
14579
+ this.recorder.connect(this.context.destination);
14580
+ });
14523
14581
  });
14524
14582
  };
14525
14583
  BVPcmRecorder.prototype.stop = function() {
@@ -14527,23 +14585,21 @@ BVPcmRecorder.prototype.stop = function() {
14527
14585
  this.audioInput.disconnect();
14528
14586
  if (this.recorder)
14529
14587
  this.recorder.disconnect();
14588
+ if (this.context)
14589
+ this.context.close();
14530
14590
  };
14531
14591
  BVPcmRecorder.prototype.init = function() {
14532
- this.context = new (window.AudioContext || window.webkitAudioContext)();
14533
- this.analyser = this.context.createAnalyser();
14534
- this.analyser.fftSize = this.fftSize;
14535
- const createScript = this.context.createScriptProcessor || this.context.createJavaScriptNode;
14536
- this.recorder = createScript.apply(
14537
- this.context,
14538
- [this.fftSize, this.config.numberChannels, this.config.numberChannels]
14539
- );
14540
- this.recorder.onaudioprocess = this.onaudioprocess.bind(this);
14541
- };
14542
- BVPcmRecorder.prototype.onaudioprocess = function(e) {
14543
- if (this.config.numberChannels === 1) {
14544
- const data = e.inputBuffer.getChannelData(0);
14545
- this.handlePcm(new Float32Array(data));
14546
- }
14592
+ return __async(this, null, function* () {
14593
+ this.context = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: this.config.sampleRate });
14594
+ this.analyser = this.context.createAnalyser();
14595
+ this.analyser.fftSize = this.fftSize;
14596
+ yield this.context.audioWorklet.addModule(audioProcessorUrl);
14597
+ this.recorder = new AudioWorkletNode(this.context, "bv-audio-processor");
14598
+ this.recorder.port.onmessage = (e) => {
14599
+ if (e.data)
14600
+ this.handlePcm(e.data);
14601
+ };
14602
+ });
14547
14603
  };
14548
14604
  BVPcmRecorder.prototype.handlePcm = function(bytes) {
14549
14605
  if (bytes[0] === 0 && bytes[1] === 0)
@@ -1,5 +1,6 @@
1
1
  import PlayerPlugin from "../../plugins/player";
2
2
  import { IDataHandle } from "src/core/events";
3
+ import { IRecordStopInfo } from "src/plugins/player/event";
3
4
  type EnumRotate = "Rotate0" | "Rotate90" | "Rotate180" | "Rotate270";
4
5
  export type IPlayerState = ReturnType<typeof CreatePlayerState>;
5
6
  export declare function CreatePlayerState(player: PlayerPlugin): {
@@ -8,10 +9,7 @@ export declare function CreatePlayerState(player: PlayerPlugin): {
8
9
  information: IDataHandle<boolean>;
9
10
  record: IDataHandle<{
10
11
  type: "recordStart" | "recordStop";
11
- recordInfo?: {
12
- data: Blob;
13
- cancelAutoDownload: () => void;
14
- } | undefined;
12
+ recordInfo?: IRecordStopInfo | undefined;
15
13
  }>;
16
14
  rotate: IDataHandle<{
17
15
  type: EnumRotate;
@@ -1,3 +1,4 @@
1
+ import { IPuOption } from "src/main";
1
2
  import { IPluginEvent, IPluginEventMap } from "../../plugins/types";
2
3
  import PlayerPlugin, { PLAYER_MODES } from "./index";
3
4
  interface IPlayerEvent extends IPluginEvent {
@@ -15,6 +16,17 @@ interface IRotateEvent extends IPlayerEvent {
15
16
  name: "rotateEvent";
16
17
  rotateDeg: number;
17
18
  }
19
+ export interface IRecordStopInfo {
20
+ data: Blob;
21
+ startTime: number;
22
+ endTime: number;
23
+ duration: number;
24
+ puOptions: IPuOption;
25
+ fileName: string;
26
+ cancelAutoDownload: () => {
27
+ download(filename?: string): void;
28
+ };
29
+ }
18
30
  export interface IPlayerPluginEventMap extends IPluginEventMap {
19
31
  init: IInitEvent;
20
32
  closeWebrtc: ICloseWebrtcEvent;
@@ -22,10 +34,7 @@ export interface IPlayerPluginEventMap extends IPluginEventMap {
22
34
  close: IPlayerEvent;
23
35
  contextmenu: Event;
24
36
  recordStart: undefined;
25
- recordStop: {
26
- data: Blob;
27
- cancelAutoDownload: () => void;
28
- };
37
+ recordStop: IRecordStopInfo;
29
38
  screenshot: undefined | {
30
39
  img: Blob;
31
40
  cancelAutoDownload: () => void;
@@ -56,6 +56,7 @@ declare class PlayerPlugin extends Plugin<HTMLDivElement, IPlayerPluginEventMap>
56
56
  private _videoOption?;
57
57
  private _pluginOption?;
58
58
  private _playerConfig;
59
+ private _puOptions?;
59
60
  private _video;
60
61
  private _spinner;
61
62
  private _toast;
@@ -1,3 +1,4 @@
1
+ import { IOnMediaRecordHandle } from "src/utils/media";
1
2
  import { IPluginEvent, IPluginEventMap, Plugin } from "./types";
2
3
  import { IPuOption } from "src/main";
3
4
  interface IVideoPluginEvent extends IPluginEvent {
@@ -52,7 +53,7 @@ declare class VideoPlugin extends Plugin<HTMLDivElement, IVideoPluginEventMap> {
52
53
  } | undefined>;
53
54
  private _genFileName;
54
55
  recordStart(): void;
55
- recordStop(onRecordInfo?: (data: Blob, cancelAutoDownload: () => void) => void): void;
56
+ recordStop(onRecordInfo?: IOnMediaRecordHandle): void;
56
57
  rotate(degStep: number): void;
57
58
  beforeDestroy(): void;
58
59
  }
@@ -1,6 +1,16 @@
1
1
  interface IStreamProvider {
2
2
  captureStream(frameRate?: number): MediaStream;
3
3
  }
4
+ export interface IOnMediaRecordHandle {
5
+ (blob: Blob, metaInfo: {
6
+ duration: number;
7
+ startTime: number;
8
+ endTime: number;
9
+ fileName: string;
10
+ }, cancelAutoDownload: () => {
11
+ download(fileName?: string): void;
12
+ }): boolean;
13
+ }
4
14
  interface IMediaOption {
5
15
  video?: boolean;
6
16
  audio?: boolean;
@@ -42,7 +52,7 @@ declare const media: {
42
52
  download(): void;
43
53
  } | undefined>;
44
54
  record: (element: IStreamProvider, stream?: MediaStream | null, fileName?: string) => [(MediaRecorder | undefined)?, (MediaStream | undefined)?, ({
45
- setOnMedia(onMedia: (blob: Blob, cancelAutoDownload: () => void) => Promise<void> | void): void;
55
+ setOnMedia(onMedia: IOnMediaRecordHandle): void;
46
56
  } | undefined)?];
47
57
  getMediaDir: (option: IMediaOption) => number;
48
58
  video2Canvas: (video: HTMLVideoElement, opts: IVideo2CanvasOptions) => ICanvasControl;
@@ -1 +1,2 @@
1
- export declare const createRecord: (_mediaStream: MediaStream, fileName: string, isDownload: (blob: Blob) => Promise<boolean>) => MediaRecorder;
1
+ import { IOnMediaRecordHandle } from "./media";
2
+ export declare const createRecord: (_mediaStream: MediaStream, fileName: string, isDownload: IOnMediaRecordHandle) => MediaRecorder;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@besovideo/webrtc-player",
3
- "version": "0.8.95",
3
+ "version": "0.8.96",
4
4
  "description": "@besovideo/webrtc-player desc",
5
5
  "type": "module",
6
6
  "types": "./dist/types/main.d.ts",