ホームページ > ウェブフロントエンド > jsチュートリアル > jsを使って録画アップロード機能を実装する方法

jsを使って録画アップロード機能を実装する方法

王林
リリース: 2020-04-15 09:21:57
転載
3172 人が閲覧しました

jsを使って録画アップロード機能を実装する方法

具体的なコードは次のとおりです:

1. HTML ページ

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

<!DOCTYPE html>

<html>

<head>

 <meta charset="UTF-8">

 <title id="title"></title>

 

</head>

<body>

<audio id="player" autoplay controls></audio>

<p>

 <button onclick="start_reco()">开始录音</button>

</p>

<p>

 <button onclick="ai_reco()" style="background-color: cornflowerblue">发送语音指令</button>

</p>

</body>

<script type="application/javascript" src="/static/jquery-3.3.1.min.js"></script>

<script type="text/javascript" src="/static/Recorder.js"></script>

<script type="application/javascript">

 var reco = null;

 var audio_context = new AudioContext();//音频内容对象

 navigator.getUserMedia = (navigator.getUserMedia ||

  navigator.webkitGetUserMedia ||

  navigator.mozGetUserMedia ||

  navigator.msGetUserMedia); // 兼容其他浏览器

 

 navigator.getUserMedia({audio: true}, create_stream, function (err) {

  console.log(err)

 });

 

 function create_stream(user_media) {

  var stream_input = audio_context.createMediaStreamSource(user_media);

  reco = new Recorder(stream_input);

 }

 

 

 function start_reco() {

  reco.record();

 }

 

 function ai_reco() {

  reco.stop();

 

  reco.exportWAV(function (wav_file) {

   console.log(wav_file);

   var formdata = new FormData(); // form 表单 {key:value}

   formdata.append("audio", wav_file); // form input type="file"

   $.ajax({

    url: "/receive_audio",

    type: &#39;post&#39;,

    processData: false,

    contentType: false,

    data: formdata,

    dataType: &#39;json&#39;,

    success: function (data) {

     console.log(data);

     document.getElementById("player").src = "/get_audio/" + data.filename;

    }

   })

  });

  reco.clear();

 }

 

</script>

</html>

ログイン後にコピー

(推奨される関連チュートリアル: js チュートリアル

2. Recorder.js の内容

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Recorder = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module &#39;"+o+"&#39;");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

"use strict";

 

module.exports = require("./recorder").Recorder;

 

},{"./recorder":2}],2:[function(require,module,exports){

&#39;use strict&#39;;

 

var _createClass = (function () {

 function defineProperties(target, props) {

  for (var i = 0; i < props.length; i++) {

   var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);

  }

 }return function (Constructor, protoProps, staticProps) {

  if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;

 };

})();

 

Object.defineProperty(exports, "__esModule", {

 value: true

});

exports.Recorder = undefined;

 

var _inlineWorker = require(&#39;inline-worker&#39;);

 

var _inlineWorker2 = _interopRequireDefault(_inlineWorker);

 

function _interopRequireDefault(obj) {

 return obj && obj.__esModule ? obj : { default: obj };

}

 

function _classCallCheck(instance, Constructor) {

 if (!(instance instanceof Constructor)) {

  throw new TypeError("Cannot call a class as a function");

 }

}

 

var Recorder = exports.Recorder = (function () {

 function Recorder(source, cfg) {

  var _this = this;

 

  _classCallCheck(this, Recorder);

 

  this.config = {

   bufferLen: 4096,

   numChannels: 2,

   mimeType: &#39;audio_pcm/wav&#39;

  };

  this.recording = false;

  this.callbacks = {

   getBuffer: [],

   exportWAV: []

  };

 

  Object.assign(this.config, cfg);

  this.context = source.context;

  this.node = (this.context.createScriptProcessor || this.context.createJavaScriptNode).call(this.context, this.config.bufferLen, this.config.numChannels, this.config.numChannels);

 

  this.node.onaudioprocess = function (e) {

   if (!_this.recording) return;

 

   var buffer = [];

   for (var channel = 0; channel < _this.config.numChannels; channel++) {

    buffer.push(e.inputBuffer.getChannelData(channel));

   }

   _this.worker.postMessage({

    command: &#39;record&#39;,

    buffer: buffer

   });

  };

 

  source.connect(this.node);

  this.node.connect(this.context.destination); //this should not be necessary

 

  var self = {};

  this.worker = new _inlineWorker2.default(function () {

   var recLength = 0,

    recBuffers = [],

    sampleRate = undefined,

    numChannels = undefined;

 

   self.onmessage = function (e) {

    switch (e.data.command) {

     case &#39;init&#39;:

      init(e.data.config);

      break;

     case &#39;record&#39;:

      record(e.data.buffer);

      break;

     case &#39;exportWAV&#39;:

      exportWAV(e.data.type);

      break;

     case &#39;getBuffer&#39;:

      getBuffer();

      break;

     case &#39;clear&#39;:

      clear();

      break;

    }

   };

 

   function init(config) {

    sampleRate = config.sampleRate;

    numChannels = config.numChannels;

    initBuffers();

   }

 

   function record(inputBuffer) {

    for (var channel = 0; channel < numChannels; channel++) {

     recBuffers[channel].push(inputBuffer[channel]);

    }

    recLength += inputBuffer[0].length;

   }

 

   function exportWAV(type) {

    var buffers = [];

    for (var channel = 0; channel < numChannels; channel++) {

     buffers.push(mergeBuffers(recBuffers[channel], recLength));

    }

    var interleaved = undefined;

    if (numChannels === 2) {

     interleaved = interleave(buffers[0], buffers[1]);

    } else {

     interleaved = buffers[0];

    }

    var dataview = encodeWAV(interleaved);

    var audioBlob = new Blob([dataview], { type: type });

 

    self.postMessage({ command: &#39;exportWAV&#39;, data: audioBlob });

   }

 

   function getBuffer() {

    var buffers = [];

    for (var channel = 0; channel < numChannels; channel++) {

     buffers.push(mergeBuffers(recBuffers[channel], recLength));

    }

    self.postMessage({ command: &#39;getBuffer&#39;, data: buffers });

   }

 

   function clear() {

    recLength = 0;

    recBuffers = [];

    initBuffers();

   }

 

   function initBuffers() {

    for (var channel = 0; channel < numChannels; channel++) {

     recBuffers[channel] = [];

    }

   }

 

   function mergeBuffers(recBuffers, recLength) {

    var result = new Float32Array(recLength);

    var offset = 0;

    for (var i = 0; i < recBuffers.length; i++) {

     result.set(recBuffers[i], offset);

     offset += recBuffers[i].length;

    }

    return result;

   }

 

   function interleave(inputL, inputR) {

    var length = inputL.length + inputR.length;

    var result = new Float32Array(length);

 

    var index = 0,

     inputIndex = 0;

 

    while (index < length) {

     result[index++] = inputL[inputIndex];

     result[index++] = inputR[inputIndex];

     inputIndex++;

    }

    return result;

   }

 

   function floatTo16BitPCM(output, offset, input) {

    for (var i = 0; i < input.length; i++, offset += 2) {

     var s = Math.max(-1, Math.min(1, input[i]));

     output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);

    }

   }

 

   function writeString(view, offset, string) {

    for (var i = 0; i < string.length; i++) {

     view.setUint8(offset + i, string.charCodeAt(i));

    }

   }

 

   function encodeWAV(samples) {

    var buffer = new ArrayBuffer(44 + samples.length * 2);

    var view = new DataView(buffer);

 

    /* RIFF identifier */

    writeString(view, 0, &#39;RIFF&#39;);

    /* RIFF chunk length */

    view.setUint32(4, 36 + samples.length * 2, true);

    /* RIFF type */

    writeString(view, 8, &#39;WAVE&#39;);

    /* format chunk identifier */

    writeString(view, 12, &#39;fmt &#39;);

    /* format chunk length */

    view.setUint32(16, 16, true);

    /* sample format (raw) */

    view.setUint16(20, 1, true);

    /* channel count */

    view.setUint16(22, numChannels, true);

    /* sample rate */

    view.setUint32(24, sampleRate, true);

    /* byte rate (sample rate * block align) */

    view.setUint32(28, sampleRate * 4, true);

    /* block align (channel count * bytes per sample) */

    view.setUint16(32, numChannels * 2, true);

    /* bits per sample */

    view.setUint16(34, 16, true);

    /* data chunk identifier */

    writeString(view, 36, &#39;data&#39;);

    /* data chunk length */

    view.setUint32(40, samples.length * 2, true);

 

    floatTo16BitPCM(view, 44, samples);

 

    return view;

   }

  }, self);

 

  this.worker.postMessage({

   command: &#39;init&#39;,

   config: {

    sampleRate: this.context.sampleRate,

    numChannels: this.config.numChannels

   }

  });

 

  this.worker.onmessage = function (e) {

   var cb = _this.callbacks[e.data.command].pop();

   if (typeof cb == &#39;function&#39;) {

    cb(e.data.data);

   }

  };

 }

 

 _createClass(Recorder, [{

  key: &#39;record&#39;,

  value: function record() {

   this.recording = true;

  }

 }, {

  key: &#39;stop&#39;,

  value: function stop() {

   this.recording = false;

  }

 }, {

  key: &#39;clear&#39;,

  value: function clear() {

   this.worker.postMessage({ command: &#39;clear&#39; });

  }

 }, {

  key: &#39;getBuffer&#39;,

  value: function getBuffer(cb) {

   cb = cb || this.config.callback;

   if (!cb) throw new Error(&#39;Callback not set&#39;);

 

   this.callbacks.getBuffer.push(cb);

 

   this.worker.postMessage({ command: &#39;getBuffer&#39; });

  }

 }, {

  key: &#39;exportWAV&#39;,

  value: function exportWAV(cb, mimeType) {

   mimeType = mimeType || this.config.mimeType;

   cb = cb || this.config.callback;

   if (!cb) throw new Error(&#39;Callback not set&#39;);

 

   this.callbacks.exportWAV.push(cb);

 

   this.worker.postMessage({

    command: &#39;exportWAV&#39;,

    type: mimeType

   });

  }

 }], [{

  key: &#39;forceDownload&#39;,

  value: function forceDownload(blob, filename) {

   var url = (window.URL || window.webkitURL).createObjectURL(blob);

   var link = window.document.createElement(&#39;a&#39;);

   link.href = url;

   link.download = filename || &#39;output.wav&#39;;

   var click = document.createEvent("Event");

   click.initEvent("click", true, true);

   link.dispatchEvent(click);

  }

 }]);

 

 return Recorder;

})();

 

exports.default = Recorder;

 

},{"inline-worker":3}],3:[function(require,module,exports){

"use strict";

 

module.exports = require("./inline-worker");

},{"./inline-worker":4}],4:[function(require,module,exports){

(function (global){

"use strict";

 

var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

 

var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };

 

var WORKER_ENABLED = !!(global === global.window && global.URL && global.Blob && global.Worker);

 

var InlineWorker = (function () {

 function InlineWorker(func, self) {

 var _this = this;

 

 _classCallCheck(this, InlineWorker);

 

 if (WORKER_ENABLED) {

  var functionBody = func.toString().trim().match(/^function\s*\w*\s*\([\w\s,]*\)\s*{([\w\W]*?)}$/)[1];

  var url = global.URL.createObjectURL(new global.Blob([functionBody], { type: "text/javascript" }));

 

  return new global.Worker(url);

 }

 

 this.self = self;

 this.self.postMessage = function (data) {

  setTimeout(function () {

  _this.onmessage({ data: data });

  }, 0);

 };

 

 setTimeout(function () {

  func.call(self);

 }, 0);

 }

 

 _createClass(InlineWorker, {

 postMessage: {

  value: function postMessage(data) {

  var _this = this;

 

  setTimeout(function () {

   _this.self.onmessage({ data: data });

  }, 0);

  }

 }

 });

 

 return InlineWorker;

})();

 

module.exports = InlineWorker;

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

},{}]},{},[1])(1)

});

ログイン後にコピー

3. Flask の記述方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

...

@app.route("/")

def index():

 return render_template("index.html")

 

@app.route("/receive_audio", methods=["POST"])

def receive_audio():

 file = request.files.get("audio")

 if file:

  filepath = os.path.join(BAISE_DIR, "data", "%s.m4a" % uuid4())

  file.save(filepath)

 

  text = baidu.auido2text(filepath)

 

  answer = tuling.chat(text)

 

  res = baidu.text2audio(answer)

  if res.get("err_no") == 200:

   return {"code": 200, "filename": res.get("filename")}

 

 return {"code": 201, "msg": "上传失败"}

 

 

@app.route("/get_audio/<filename>")

def get_audio(filename):

 return send_file(os.path.join(BAISE_DIR, "data", filename))

 

...

ログイン後にコピー

注: Flask の起動 IP は 127.0.0.1、その他と記述されますaddress js がエラーを報告する可能性があります。

以上がjsを使って録画アップロード機能を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート