ipyaudio 0.1.9__py3-none-any.whl → 0.1.11__py3-none-any.whl

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.
Files changed (34) hide show
  1. ipyaudio/_frontend.py +1 -1
  2. ipyaudio/_version.py +1 -1
  3. ipyaudio/labextension/package.json +2 -2
  4. ipyaudio/labextension/static/424.ca45437f3ff02b14458c.js +1 -0
  5. ipyaudio/nbextension/index.js +1 -1
  6. ipyaudio/nbextension/index.js.map +1 -1
  7. ipyaudio/player.py +9 -7
  8. ipyaudio/recorder.py +66 -27
  9. ipyaudio/widget.py +5 -1
  10. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/package.json +2 -2
  11. ipyaudio-0.1.11.data/data/share/jupyter/labextensions/ipyaudio/static/424.ca45437f3ff02b14458c.js +1 -0
  12. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/nbextensions/ipyaudio/index.js +1 -1
  13. ipyaudio-0.1.11.data/data/share/jupyter/nbextensions/ipyaudio/index.js.map +1 -0
  14. {ipyaudio-0.1.9.dist-info → ipyaudio-0.1.11.dist-info}/METADATA +1 -1
  15. ipyaudio-0.1.11.dist-info/RECORD +45 -0
  16. ipyaudio/labextension/static/424.6dd9a8a74e4a88bf8b52.js +0 -1
  17. ipyaudio/labextension/static/remoteEntry.f9ac547af445a24b6fc2.js +0 -1
  18. ipyaudio-0.1.9.data/data/share/jupyter/labextensions/ipyaudio/static/424.6dd9a8a74e4a88bf8b52.js +0 -1
  19. ipyaudio-0.1.9.data/data/share/jupyter/labextensions/ipyaudio/static/remoteEntry.f9ac547af445a24b6fc2.js +0 -1
  20. ipyaudio-0.1.9.data/data/share/jupyter/nbextensions/ipyaudio/index.js.map +0 -1
  21. ipyaudio-0.1.9.dist-info/RECORD +0 -47
  22. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/etc/jupyter/nbconfig/notebook.d/ipyaudio.json +0 -0
  23. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/install.json +0 -0
  24. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/static/122.3700f0454aee82938e32.js +0 -0
  25. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/static/509.a9d6860fe38ae60aa71f.js +0 -0
  26. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/static/570.97f2a8196b7f1703e636.js +0 -0
  27. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/static/570.97f2a8196b7f1703e636.js.LICENSE.txt +0 -0
  28. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/static/58.0e2f3d700c41688625fe.js +0 -0
  29. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/static/style.js +0 -0
  30. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/labextensions/ipyaudio/static/third-party-licenses.json +0 -0
  31. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/nbextensions/ipyaudio/extension.js +0 -0
  32. {ipyaudio-0.1.9.data → ipyaudio-0.1.11.data}/data/share/jupyter/nbextensions/ipyaudio/index.js.LICENSE.txt +0 -0
  33. {ipyaudio-0.1.9.dist-info → ipyaudio-0.1.11.dist-info}/WHEEL +0 -0
  34. {ipyaudio-0.1.9.dist-info → ipyaudio-0.1.11.dist-info}/licenses/LICENSE.txt +0 -0
ipyaudio/player.py CHANGED
@@ -34,16 +34,16 @@ class Player(DOMWidget, ValueWidget):
34
34
  _view_module = Unicode(module_name).tag(sync=True)
35
35
  _view_module_version = Unicode(module_version).tag(sync=True)
36
36
 
37
- config = json.loads(files("ipyaudio.configs").joinpath("player.json").read_text(encoding="utf-8"))
38
- config = Dict(config).tag(sync=True)
37
+ config = Dict({}).tag(sync=True)
38
+ language = Unicode("en").tag(sync=True)
39
+ verbose = Bool(False).tag(sync=True)
40
+
39
41
  audio = Unicode("").tag(sync=True)
40
42
  rate = Int(16000).tag(sync=True)
41
43
  is_streaming = Bool(False).tag(sync=True)
42
44
  is_done = Bool(False).tag(sync=True)
43
- language = Unicode("en").tag(sync=True)
44
45
  latency = Int(0).tag(sync=True)
45
46
  rtf = Float(0).tag(sync=True)
46
- verbose = Bool(False).tag(sync=True)
47
47
 
48
48
  def __init__(
49
49
  self,
@@ -55,13 +55,15 @@ class Player(DOMWidget, ValueWidget):
55
55
  **kwargs,
56
56
  ):
57
57
  super().__init__(**kwargs)
58
+ config_path = files("ipyaudio.configs").joinpath("player.json")
59
+ self.config = merge_dicts(json.loads(config_path.read_text(encoding="utf-8")), config)
60
+ self.language = language.lower()
61
+ self.verbose = verbose
62
+
58
63
  self._audio = audio
59
64
  if rate is not None:
60
65
  self.rate = rate
61
- self.config = merge_dicts(self.config, config)
62
66
  self.is_streaming = isinstance(audio, (AsyncGeneratorType, GeneratorType))
63
- self.language = language.lower()
64
- self.verbose = verbose
65
67
  if self.is_streaming and self.verbose:
66
68
  self.duration = 0
67
69
  self.latency_label = Label()
ipyaudio/recorder.py CHANGED
@@ -7,12 +7,13 @@
7
7
  import json
8
8
  from functools import partial
9
9
  from importlib.resources import files
10
+ from time import time
10
11
 
11
12
  import numpy as np
12
13
  from audiolab import StreamReader, Writer, filters
13
14
  from ipydatawidgets import NDArray, array_serialization, shape_constraints
14
15
  from IPython.display import display
15
- from ipywidgets import DOMWidget, ValueWidget, register
16
+ from ipywidgets import DOMWidget, Label, ValueWidget, VBox, register
16
17
  from traitlets import Bool, Dict, Int, Unicode
17
18
 
18
19
  from ._frontend import module_name, module_version
@@ -29,68 +30,106 @@ class Recorder(DOMWidget, ValueWidget):
29
30
  _view_module = Unicode(module_name).tag(sync=True)
30
31
  _view_module_version = Unicode(module_version).tag(sync=True)
31
32
 
32
- config = json.loads(files("ipyaudio.configs").joinpath("recorder.json").read_text(encoding="utf-8"))
33
- player_config = json.loads(files("ipyaudio.configs").joinpath("player.json").read_text(encoding="utf-8"))
34
- config = Dict(config).tag(sync=True)
35
- player_config = Dict(player_config).tag(sync=True)
33
+ config = Dict({}).tag(sync=True)
34
+ player_config = Dict({}).tag(sync=True)
35
+ sync = Bool(False).tag(sync=True)
36
36
  language = Unicode("en").tag(sync=True)
37
+ verbose = Bool(False).tag(sync=True)
37
38
 
38
- chunk = NDArray(dtype=np.uint8, default_value=np.zeros((0,), dtype=np.uint8))
39
- chunk = chunk.tag(sync=True, **array_serialization).valid(
40
- shape_constraints(
41
- None,
42
- )
39
+ # 48000 Hz, WebM, mono
40
+ chunk = (
41
+ NDArray(dtype=np.uint8, default_value=np.zeros((0,), dtype=np.uint8))
42
+ .tag(sync=True, **array_serialization)
43
+ .valid(shape_constraints(None))
44
+ )
45
+ frame = (
46
+ NDArray(dtype=np.float32, default_value=np.zeros((1, 0), dtype=np.float32))
47
+ .tag(sync=True, **array_serialization)
48
+ .valid(shape_constraints(None, None))
43
49
  )
44
- frame = NDArray(dtype=np.float32, default_value=np.zeros((1, 0), dtype=np.float32))
45
- frame = frame.tag(sync=True, **array_serialization).valid(shape_constraints(None, None))
46
50
  rate = Int(16000).tag(sync=True)
47
- end = Bool(True).tag(sync=True)
51
+ completed = Bool(True).tag(sync=True)
48
52
 
49
53
  def __init__(
50
54
  self,
51
55
  filename: str = None,
52
56
  config: dict = {},
53
57
  player_config: dict = {},
58
+ sync: bool = False,
54
59
  language: str = "en",
55
60
  verbose: bool = False,
56
61
  **kwargs,
57
62
  ):
58
63
  super().__init__(**kwargs)
64
+ config_path = files("ipyaudio.configs").joinpath("recorder.json")
65
+ player_config_path = files("ipyaudio.configs").joinpath("player.json")
66
+ self.config = merge_dicts(json.loads(config_path.read_text(encoding="utf-8")), config)
67
+ self.player_config = merge_dicts(json.loads(player_config_path.read_text(encoding="utf-8")), player_config)
68
+ self.sync = sync
69
+ self.language = language.lower()
70
+ self.verbose = verbose
71
+ self.start = time()
72
+
59
73
  self.audio = np.zeros((1, 0), dtype=np.float32)
60
74
  self.aformat = partial(filters.aformat, sample_fmts="flt", channel_layouts=1)
61
75
  self.stream_reader = StreamReader(filters=[self.aformat(sample_rates=self.rate)], frame_size=1024)
62
76
  self.writer = None
63
77
  if filename is not None:
64
78
  self.writer = Writer(filename, codec_name="pcm_f32le", format="flt", layout="mono", rate=self.rate)
65
-
66
- self.config = merge_dicts(self.config, config)
67
- self.player_config = merge_dicts(self.player_config, player_config)
68
- self.language = language.lower()
69
- self.verbose = verbose
70
79
  self.observe(self._on_chunk_change, names="chunk")
71
- self.observe(self._on_end_change, names="end")
80
+ self.observe(self._on_completed_change, names="completed")
72
81
  self.observe(self._on_rate_change, names="rate")
73
- display(self)
82
+ if self.sync and self.verbose:
83
+ self.output_label = Label()
84
+ self.rtf_label = Label()
85
+ display(VBox([self, self.output_label, self.rtf_label]))
86
+ else:
87
+ display(self)
88
+
89
+ def _log_chunk(self, chunk):
90
+ chunk_bytes = chunk.shape[0]
91
+ recieved_bytes = self.stream_reader.bytestream.getbuffer().nbytes
92
+ decoded_seconds = self.audio.shape[1] / self.rate
93
+ self.output_label.value = "Chunk received" if self.language == "en" else "收到数据"
94
+ self.output_label.value += f": {chunk_bytes}B/{recieved_bytes / 1024:.2f}KB ({decoded_seconds:.2f}s)."
95
+ label = "实时率" if self.language == "zh" else "Real-Time Factor"
96
+ if self.audio.shape[1] > 0:
97
+ cost_time = time() - self.start
98
+ decoded_seconds = self.audio.shape[1] / self.rate
99
+ self.rtf_label.value = f"{label}: {cost_time / decoded_seconds:.2f}"
100
+ else:
101
+ self.rtf_label.value = f"{label}: 0.00"
74
102
 
75
103
  def _on_chunk_change(self, change):
76
- # 48000 Hz, WebM, mono
104
+ # The comm API is a symmetric, asynchronous, `fire and forget` style messaging API.
105
+ # Sends a message to the frontend to indicate that a chunk has been received.
106
+ self.send({"msg_type": "chunk_received"})
107
+
108
+ if self.verbose:
109
+ self._log_chunk(change["new"])
77
110
  self.stream_reader.push(change["new"].tobytes())
78
111
  for frame, _ in self.stream_reader.pull():
79
112
  self.audio = np.concatenate((self.audio, frame), axis=1)
80
113
  self.frame = frame
81
114
 
82
- def _on_end_change(self, change):
83
- if change["new"]:
115
+ def _on_completed_change(self, change):
116
+ if self.verbose:
117
+ self.output_label.value = "Completed" if self.language == "en" else "完成"
118
+ if not change["new"]:
119
+ if self.verbose:
120
+ self.output_label.value = "Start recording." if self.language == "en" else "开始录音."
121
+ self.start = time()
122
+ self.audio = np.zeros((1, 0), dtype=np.float32)
123
+ self.stream_reader.reset()
124
+ else:
125
+ if self.verbose:
126
+ self.output_label.value = "End recording." if self.language == "en" else "结束录音."
84
127
  for frame, _ in self.stream_reader.pull(partial=True):
85
128
  self.audio = np.concatenate((self.audio, frame), axis=1)
86
129
  self.frame = frame
87
130
  if self.writer is not None:
88
131
  self.writer.write(self.audio)
89
132
  self.writer.close()
90
- else:
91
- # Reset before recording
92
- self.audio = np.zeros((1, 0), dtype=np.float32)
93
- self.stream_reader.reset()
94
133
 
95
134
  def _on_rate_change(self, change):
96
135
  self.stream_reader.filters = [self.aformat(sample_rates=self.rate)]
ipyaudio/widget.py CHANGED
@@ -4,6 +4,7 @@
4
4
  # Copyright (c) Zhendong Peng.
5
5
  # Distributed under the terms of the Modified BSD License.
6
6
 
7
+ import time
7
8
  from pathlib import Path
8
9
  from types import AsyncGeneratorType, GeneratorType
9
10
  from typing import Optional, Union
@@ -24,7 +25,10 @@ def play(
24
25
  language: str = "en",
25
26
  verbose: bool = False,
26
27
  ):
27
- Player(audio, rate, config, language, verbose).play()
28
+ player = Player(audio, rate, config, language, verbose)
29
+ # Wait for the player to be initialized
30
+ time.sleep(0.1)
31
+ player.play()
28
32
 
29
33
 
30
34
  def record(
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ipyaudio",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "A Custom Jupyter Widget Library",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -101,7 +101,7 @@
101
101
  }
102
102
  },
103
103
  "_build": {
104
- "load": "static/remoteEntry.f9ac547af445a24b6fc2.js",
104
+ "load": "static",
105
105
  "extension": "./extension"
106
106
  }
107
107
  },
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkipyaudio=self.webpackChunkipyaudio||[]).push([[424],{319:function(e,t,i){var n=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))((function(s,a){function r(e){try{l(n.next(e))}catch(e){a(e)}}function o(e){try{l(n.throw(e))}catch(e){a(e)}}function l(e){var t;e.done?s(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(r,o)}l((n=n.apply(e,t||[])).next())}))},s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.RecorderView=t.RecorderModel=void 0;const a=s(i(5364)),r=i(3459),o=i(3983),l=i(1797),c=s(i(8020));i(6378),i(1463);class d extends o.DOMWidgetModel{defaults(){return Object.assign(Object.assign({},super.defaults()),{_model_name:d.model_name,_model_module:d.model_module,_model_module_version:d.model_module_version,_view_name:d.view_name,_view_module:d.view_module,_view_module_version:d.view_module_version,chunk:new Uint8Array(0),rate:16e3,end:!1})}}t.RecorderModel=d,d.serializers=Object.assign(Object.assign({},o.DOMWidgetModel.serializers),{chunk:r.simplearray_serialization}),d.model_name="RecorderModel",d.model_module=l.MODULE_NAME,d.model_module_version=l.MODULE_VERSION,d.view_name="RecorderView",d.view_module=l.MODULE_NAME,d.view_module_version=l.MODULE_VERSION;class u extends o.DOMWidgetView{constructor(){super(...arguments),this._chunks=[],this._isFirstChunk=!0,this._isCompleted=!1}_sendChunk(){if(this._chunks.length>0){const e=this._chunks[0];this.model.set("chunk",{array:e,shape:[e.length]}),this.model.save_changes(),this._chunks.shift()}else this._isCompleted&&(this.model.set("completed",!0),this.model.save_changes())}render(){super.render(),this.displayed.then((()=>n(this,void 0,void 0,(function*(){const e=this.model.get("language");this._recorder=c.default.create((0,a.default)({},this.model.get("config"),{language:e}),(0,a.default)({},this.model.get("player_config"),{language:e})),this.el.appendChild(this._recorder.el),this.model.on("msg:custom",(e=>n(this,void 0,void 0,(function*(){var t;const i=3e3+(null!==(t=this._recorder.timeSlice)&&void 0!==t?t:32),n=Date.now();if("chunk_received"===e.msg_type){for(;0===this._chunks.length&&Date.now()-n<i;)yield new Promise((e=>setTimeout(e,32)));this._sendChunk()}})))),this._recorder.onRecordStart((()=>{this._isCompleted=!1,this._isFirstChunk=!0,this.model.set("completed",!1),this.model.set("rate",this._recorder.sampleRate),this.model.save_changes()})),this._recorder.onRecordChunk((e=>n(this,void 0,void 0,(function*(){this._chunks.push(new Uint8Array(yield e.arrayBuffer())),this.model.get("sync")&&this._isFirstChunk&&(this._isFirstChunk=!1,this._sendChunk())})))),this._recorder.onRecordEnd((e=>n(this,void 0,void 0,(function*(){this._isCompleted=!0,this.model.get("sync")||(this.model.set("completed",!0),this.model.save_changes())}))))}))))}}t.RecorderView=u},1144:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 16 16%27 fill=%27%23fff%27%3e%3cpath d=%27M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z%27/%3e%3c/svg%3e"},1463:(e,t,i)=>{i.r(t),i.d(t,{default:()=>v});var n=i(5072),s=i.n(n),a=i(7825),r=i.n(a),o=i(7659),l=i.n(o),c=i(5056),d=i.n(c),u=i(540),h=i.n(u),m=i(1113),p=i.n(m),_=i(4930),g={};g.styleTagTransform=p(),g.setAttributes=d(),g.insert=l().bind(null,"head"),g.domAPI=r(),g.insertStyleElement=h(),s()(_.A,g);const v=_.A&&_.A.locals?_.A.locals:void 0},1797:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MODULE_NAME=t.MODULE_VERSION=void 0;const n=i(8330);t.MODULE_VERSION=n.version,t.MODULE_NAME=n.name},2247:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 30 30%27%3e%3cpath stroke=%27rgba%2833, 37, 41, 0.75%29%27 stroke-linecap=%27round%27 stroke-miterlimit=%2710%27 stroke-width=%272%27 d=%27M4 7h22M4 15h22M4 23h22%27/%3e%3c/svg%3e"},3385:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%27-4 -4 8 8%27%3e%3ccircle r=%272%27 fill=%27%23fff%27/%3e%3c/svg%3e"},4274:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 20 20%27%3e%3cpath fill=%27none%27 stroke=%27%23fff%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27 stroke-width=%273%27 d=%27M6 10h8%27/%3e%3c/svg%3e"},4364:function(e,t,i){var n=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))((function(s,a){function r(e){try{l(n.next(e))}catch(e){a(e)}}function o(e){try{l(n.throw(e))}catch(e){a(e)}}function l(e){var t;e.done?s(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(r,o)}l((n=n.apply(e,t||[])).next())}))},s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.PlayerView=t.PlayerModel=void 0;const a=s(i(5364)),r=i(3983),o=i(1797),l=s(i(9155));i(6378),i(1463);class c extends r.DOMWidgetModel{defaults(){return Object.assign(Object.assign({},super.defaults()),{_model_name:c.model_name,_model_module:c.model_module,_model_module_version:c.model_module_version,_view_name:c.view_name,_view_module:c.view_module,_view_module_version:c.view_module_version})}}t.PlayerModel=c,c.serializers=Object.assign({},r.DOMWidgetModel.serializers),c.model_name="PlayerModel",c.model_module=o.MODULE_NAME,c.model_module_version=o.MODULE_VERSION,c.view_name="PlayerView",c.view_module=o.MODULE_NAME,c.view_module_version=o.MODULE_VERSION;class d extends r.DOMWidgetView{render(){super.render(),this.displayed.then((()=>n(this,void 0,void 0,(function*(){const e={isStreaming:this.model.get("is_streaming"),language:this.model.get("language")};this._player=l.default.create((0,a.default)({},this.model.get("config"),e)),this.el.appendChild(this._player.el),this.model.on("change:audio",(()=>{this._player.sampleRate=this.model.get("rate"),this._player.load(this.model.get("audio"))})),this.model.on("change:is_done",(()=>{this._player.setDone()}))}))))}}t.PlayerView=d},4718:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%27-4 -4 8 8%27%3e%3ccircle r=%273%27 fill=%27%23fff%27/%3e%3c/svg%3e"},4930:(e,t,i)=>{i.d(t,{A:()=>o});var n=i(1601),s=i.n(n),a=i(6314),r=i.n(a)()(s());r.push([e.id,".waveform {\n background-color: black;\n cursor: pointer;\n position: relative;\n width: 100%;\n}\n\n.duration, .time {\n background: rgba(0, 0, 0, 0.75);\n color: #DDDD;\n font-size: 11px;\n position: absolute;\n bottom: 0;\n z-index: 11;\n}\n\n.duration {\n right: 0;\n}\n\n.time {\n left: 0;\n}\n",""]);const o=r},5372:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 12 12%27 width=%2712%27 height=%2712%27 fill=%27none%27 stroke=%27%23dc3545%27%3e%3ccircle cx=%276%27 cy=%276%27 r=%274.5%27/%3e%3cpath stroke-linejoin=%27round%27 d=%27M5.8 3.6h.4L6 6.5z%27/%3e%3ccircle cx=%276%27 cy=%278.2%27 r=%27.6%27 fill=%27%23dc3545%27 stroke=%27none%27/%3e%3c/svg%3e"},5419:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 20 20%27%3e%3cpath fill=%27none%27 stroke=%27%23fff%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27 stroke-width=%273%27 d=%27m6 10 3 3 6-6%27/%3e%3c/svg%3e"},5531:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 16 16%27%3e%3cpath fill=%27none%27 stroke=%27%23343a40%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27 stroke-width=%272%27 d=%27m2 5 6 6 6-6%27/%3e%3c/svg%3e"},5782:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%27-4 -4 8 8%27%3e%3ccircle r=%273%27 fill=%27%2386b7fe%27/%3e%3c/svg%3e"},5932:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 16 16%27 fill=%27%23fff%27%3e%3cpath d=%27M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z%27/%3e%3c/svg%3e"},6366:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 30 30%27%3e%3cpath stroke=%27rgba%28255, 255, 255, 0.55%29%27 stroke-linecap=%27round%27 stroke-miterlimit=%2710%27 stroke-width=%272%27 d=%27M4 7h22M4 15h22M4 23h22%27/%3e%3c/svg%3e"},6690:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 16 16%27 fill=%27%236ea8fe%27%3e%3cpath fill-rule=%27evenodd%27 d=%27M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z%27/%3e%3c/svg%3e"},7115:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 16 16%27%3e%3cpath fill=%27none%27 stroke=%27%23dee2e6%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27 stroke-width=%272%27 d=%27m2 5 6 6 6-6%27/%3e%3c/svg%3e"},7154:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%27-4 -4 8 8%27%3e%3ccircle r=%273%27 fill=%27rgba%280, 0, 0, 0.25%29%27/%3e%3c/svg%3e"},7210:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 16 16%27 fill=%27none%27 stroke=%27%23052c65%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3e%3cpath d=%27M2 5L8 11L14 5%27/%3e%3c/svg%3e"},7249:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 16 16%27 fill=%27%23000%27%3e%3cpath d=%27M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z%27/%3e%3c/svg%3e"},7326:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 16 16%27 fill=%27none%27 stroke=%27%23212529%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3e%3cpath d=%27M2 5L8 11L14 5%27/%3e%3c/svg%3e"},7997:(e,t)=>{function i(e){const t=e.numFrames,i=e.numChannels||2,n=e.sampleRate||44100,s=e.isFloat?4:2,a=e.isFloat?3:1,r=i*s,o=n*r,l=t*r,c=new ArrayBuffer(44),d=new DataView(c);let u=0;function h(e){for(let t=0;t<e.length;t++)d.setUint8(u+t,e.charCodeAt(t));u+=e.length}function m(e){d.setUint32(u,e,!0),u+=4}function p(e){d.setUint16(u,e,!0),u+=2}return h("RIFF"),m(l+36),h("WAVE"),h("fmt "),m(16),p(a),p(i),m(n),m(o),p(r),p(8*s),h("data"),m(l),new Uint8Array(c)}function n(e,t){if(!e)return new Uint8Array;let n,s;e instanceof ArrayBuffer?(n=i({isFloat:!1,numChannels:t.numChannels,sampleRate:t.sampleRate,numFrames:e.byteLength/Int16Array.BYTES_PER_ELEMENT}),s=new Uint8Array(e)):(n=i({isFloat:!1,numChannels:e.numberOfChannels,sampleRate:e.sampleRate,numFrames:e.length}),s=new Uint8Array(function(e){const{numberOfChannels:t,length:i}=e,n=new Int16Array(i*t);for(let s=0;s<t;s++){const a=e.getChannelData(s),r=a instanceof Float32Array;for(let e=0;e<i;e++)n[e*t+s]=r?32767*a[e]:a[e]}return n}(e).buffer));const a=new Uint8Array(n.length+s.length);return a.set(n,0),a.set(s,n.length),a}Object.defineProperty(t,"__esModule",{value:!0}),t.createObjectURL=t.formatTime=t.createElement=void 0,t.createElement=(e,t,i="")=>{const n=document.createElement(e);return n.className=t,n.innerHTML=i,n},t.formatTime=e=>`${Math.floor(e/60)}:${("0"+Math.round(e)%60).slice(-2)}`,t.createObjectURL=(e,t={numChannels:1,sampleRate:44100})=>{let i;return i=e instanceof AudioBuffer?n(e,{numChannels:e.numberOfChannels,sampleRate:e.sampleRate}):n(e,t),URL.createObjectURL(new Blob([i],{type:"audio/wav"}))}},8020:function(e,t,i){var n=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))((function(s,a){function r(e){try{l(n.next(e))}catch(e){a(e)}}function o(e){try{l(n.throw(e))}catch(e){a(e)}}function l(e){var t;e.done?s(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(r,o)}l((n=n.apply(e,t||[])).next())}))},s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const a=s(i(423)),r=s(i(8429)),o=s(i(9155)),l=i(7997);class c{constructor(e,t){this.el=(0,l.createElement)("div","lm-Widget"),this._container=(0,l.createElement)("div","waveform"),this._currentTime=(0,l.createElement)("div","time","0:00"),this._container.append(this._currentTime),this._config=e,this._player=o.default.create(t)}get sampleRate(){return this._wavesurfer.options.sampleRate}get timeSlice(){var e;return null===(e=this._config.recordOptions)||void 0===e?void 0:e.mediaRecorderTimeslice}set sampleRate(e){this._wavesurfer.options.sampleRate=e,this._player.sampleRate=e}createWaveSurfer(){this._wavesurfer=a.default.create(Object.assign(Object.assign({},this._config.options),{container:this._container}))}createRateSelect(){this._rateSelect=(0,l.createElement)("select","form-select-sm d-inline-block me-3 my-3 w-25"),[8e3,16e3,22050,24e3,44100,48e3].forEach((e=>{const t=document.createElement("option");t.value=e.toString(),t.text=`${e} Hz`,16e3===e&&(t.selected=!0),this._rateSelect.appendChild(t)}))}createMicSelect(){this._micSelect=(0,l.createElement)("select","form-select-sm d-inline-block me-3 my-3 w-50"),navigator.mediaDevices.getUserMedia({audio:!0,video:!1}).then((e=>{r.default.getAvailableAudioDevices().then((e=>{e.forEach((e=>{const t=document.createElement("option");t.value=e.deviceId,t.text=e.label||e.deviceId,this._micSelect.appendChild(t)}))}))})).catch((e=>{const t="zh"===this._config.language?"访问麦克风失败":"Error accessing the microphone: ";throw new Error(t+e.message)}))}createPauseButton(){this._pauseButton=(0,l.createElement)("button","btn btn-outline-danger me-3 my-3",'<i class="fa fa-pause"></i>'),this._pauseButton.disabled=!0,this._pauseButton.onclick=()=>{this._recorder.isRecording()?(this._recorder.pauseRecording(),this._pauseButton.innerHTML='<i class="fa fa-play"></i>',this._container.style.display="none",this._player.el.style.display="block"):(this._recorder.resumeRecording(),this._pauseButton.innerHTML='<i class="fa fa-pause"></i>',this._container.style.display="block",this._player.el.style.display="none")}}createRecordButton(){this._recordButton=(0,l.createElement)("button","btn btn-danger me-3 my-3",'<i class="fa fa-microphone"></i>'),this._recordButton.onclick=()=>{this._recorder.isRecording()||this._recorder.isPaused()?(this._recorder.stopRecording(),this._container.style.display="none",this._player.el.style.display="block"):(this._wavesurfer.options.normalize=!1,this.sampleRate=parseInt(this._rateSelect.value),this._recorder.startRecording({deviceId:this._micSelect.value}).then((()=>{this._pauseButton.disabled=!1,this._rateSelect.disabled=!0,this._micSelect.disabled=!0,this._pauseButton.innerHTML='<i class="fa fa-pause"></i>',this._recordButton.innerHTML='<i class="fa fa-stop"></i>',this._container.style.display="block",this._player.el.style.display="none"})))}}onRecordStart(e){this._recorder.on("record-start",(()=>{e()}))}onRecordChunk(e){this._recorder.on("record-data-available",(t=>{e(t)}))}onRecordEnd(e){this._recorder.on("record-end",(t=>n(this,void 0,void 0,(function*(){this._player.load(URL.createObjectURL(t)),this._recordButton.disabled=!0,this._pauseButton.disabled=!0,yield e(t),this._recordButton.disabled=!1,this._pauseButton.disabled=!0,this._rateSelect.disabled=!1,this._micSelect.disabled=!1,this._pauseButton.innerHTML='<i class="fa fa-play"></i>',this._recordButton.innerHTML='<i class="fa fa-microphone"></i>'}))))}createRecorder(){this._wavesurfer.toggleInteraction(!1),this._recorder=this._wavesurfer.registerPlugin(r.default.create(this._config.recordOptions)),this.createRateSelect(),this.createMicSelect(),this.createPauseButton(),this.createRecordButton(),this._container.style.display="none",this._player.el.style.display="none",this.el.append(this._recordButton,this._pauseButton,this._rateSelect,this._micSelect,this._container,this._player.el),this._recorder.on("record-pause",(e=>{this._player.load(URL.createObjectURL(e))})),this._recorder.on("record-progress",(e=>{this._currentTime.textContent=(0,l.formatTime)(e/1e3)}))}static create(e,t){const i=new c(e,t);return i.createWaveSurfer(),i.createRecorder(),i}}t.default=c},8078:function(e,t,i){var n=this&&this.__awaiter||function(e,t,i,n){return new(i||(i=Promise))((function(s,a){function r(e){try{l(n.next(e))}catch(e){a(e)}}function o(e){try{l(n.throw(e))}catch(e){a(e)}}function l(e){var t;e.done?s(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(r,o)}l((n=n.apply(e,t||[])).next())}))};Object.defineProperty(t,"__esModule",{value:!0}),t.PCMPlayer=void 0;const s=i(7997);class a{constructor(e){this._isDone=!1,this._isPlaying=!0,this._samples=new Int16Array(0),this._allSamples=new Int16Array(0),this._options=Object.assign({channels:1,sampleRate:16e3,flushTime:100,language:"en"},e),this.playButton=(0,s.createElement)("button","btn btn-danger me-3 my-3",'<i class="fa fa-pause"></i>'),this.playButton.onclick=()=>{this._isPlaying=!this._isPlaying,this._isPlaying?this.play():this.pause(),this.playButton.innerHTML=`<i class="fa fa-${this._isPlaying?"pause":"play"}"></i>`},this._interval=window.setInterval(this.flush.bind(this),this._options.flushTime),this._audioCtx=new(window.AudioContext||window.webkitAudioContext),this._gainNode=this._audioCtx.createGain(),this._gainNode.gain.value=1,this._gainNode.connect(this._audioCtx.destination),this._startTime=this._audioCtx.currentTime}set sampleRate(e){this._options.sampleRate=e}setDone(){this._isDone=!0}feed(e){const t=atob(e),i=new ArrayBuffer(t.length),n=new Uint8Array(i);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);const s=new Int16Array(i);this._samples=new Int16Array([...this._samples,...s]),this._allSamples=new Int16Array([...this._allSamples,...s])}get url(){return(0,s.createObjectURL)(this._allSamples.buffer,{numChannels:this._options.channels,sampleRate:this._options.sampleRate})}flush(){if(!this._samples.length)return;const e=this._isDone,t=this._audioCtx.createBufferSource(),i=this._samples.length/this._options.channels,n=this._audioCtx.createBuffer(this._options.channels,i,this._options.sampleRate);for(let e=0;e<this._options.channels;e++){const t=n.getChannelData(e);let s=e;for(let e=0;e<i;e++)t[e]=this._samples[s]/32768,s+=this._options.channels}this._startTime=Math.max(this._startTime,this._audioCtx.currentTime),t.buffer=n,t.connect(this._gainNode),t.start(this._startTime),t.onended=()=>{this.playButton.disabled=!!e},this._startTime+=n.duration,this._samples=new Int16Array(0)}play(){return n(this,void 0,void 0,(function*(){yield this._audioCtx.resume()}))}pause(){return n(this,void 0,void 0,(function*(){yield this._audioCtx.suspend()}))}volume(e){this._gainNode.gain.value=e}destroy(){this._interval&&clearInterval(this._interval),this._samples=new Int16Array(0),this._audioCtx.close()}}t.PCMPlayer=a,t.default=a},8330:e=>{e.exports=JSON.parse('{"name":"ipyaudio","version":"0.1.11","description":"A Custom Jupyter Widget Library","keywords":["jupyter","jupyterlab","jupyterlab-extension","widgets"],"files":["lib/**/*.js","dist/*.js","css/*.css"],"homepage":"https://github.com/pengzhendong/ipyaudio","bugs":{"url":"https://github.com/pengzhendong/ipyaudio/issues"},"license":"BSD-3-Clause","author":{"name":"Zhendong Peng","email":"pzd17@tsinghua.org.cn"},"main":"lib/index.js","types":"./lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/pengzhendong/ipyaudio.git"},"scripts":{"build":"jlpm run build:lib && jlpm run build:nbextension && jlpm run build:labextension:dev","build:prod":"jlpm run build:lib && jlpm run build:nbextension && jlpm run build:labextension","build:labextension":"jupyter labextension build .","build:labextension:dev":"jupyter labextension build --development True .","build:lib":"tsc","build:nbextension":"webpack","clean":"jlpm run clean:lib && jlpm run clean:nbextension && jlpm run clean:labextension","clean:lib":"rimraf lib","clean:labextension":"rimraf ipyaudio/labextension","clean:nbextension":"rimraf ipyaudio/nbextension/static/index.js","lint":"eslint . --ext .ts,.tsx --fix","lint:check":"eslint . --ext .ts,.tsx","prepack":"jlpm run build:lib","test":"jest","watch":"npm-run-all -p \\"watch:*\\"","watch:lib":"tsc -w","watch:nbextension":"webpack --watch --mode=development","watch:labextension":"jupyter labextension watch ."},"dependencies":{"@jupyter-widgets/base":"^1.1.10 || ^2 || ^3 || ^4 || ^5 || ^6","bootstrap":"^5.3.3","jupyter-dataserializers":"^3.0.1","lodash.merge":"^4.6.2"},"devDependencies":{"@babel/core":"^7.23.7","@babel/preset-env":"^7.23.8","@jupyter-widgets/base-manager":"^1.0.7","@jupyterlab/builder":"^4.0.11","@lumino/application":"^2.3.0","@lumino/widgets":"^2.3.1","@types/jest":"^29.5.11","@types/webpack-env":"^1.18.4","@typescript-eslint/eslint-plugin":"^6.19.1","@typescript-eslint/parser":"^6.19.1","acorn":"^8.11.3","css-loader":"^6.9.1","eslint":"^8.56.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","fs-extra":"^11.2.0","identity-obj-proxy":"^3.0.0","jest":"^29.7.0","mkdirp":"^3.0.1","npm-run-all":"^4.1.5","prettier":"^3.2.4","rimraf":"^5.0.5","source-map-loader":"^5.0.0","style-loader":"^3.3.4","ts-jest":"^29.1.2","ts-loader":"^9.5.1","typescript":"~5.3.3","wavesurfer.js":"^7.9.1","webpack":"^5.90.0","webpack-cli":"^5.1.4"},"devDependenciesComments":{"@jupyterlab/builder":"pinned to the latest JupyterLab 3.x release","@lumino/application":"pinned to the latest Lumino 1.x release","@lumino/widgets":"pinned to the latest Lumino 1.x release"},"jupyterlab":{"extension":"lib/plugin","outputDir":"ipyaudio/labextension/","sharedPackages":{"@jupyter-widgets/base":{"bundled":false,"singleton":true}}},"packageManager":"yarn@4.8.1"}')},8487:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 8 8%27%3e%3cpath fill=%27%23198754%27 d=%27M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z%27/%3e%3c/svg%3e"},8734:e=>{e.exports="data:image/svg+xml,%3csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%27-4 -4 8 8%27%3e%3ccircle r=%273%27 fill=%27rgba%28255, 255, 255, 0.25%29%27/%3e%3c/svg%3e"},9155:function(e,t,i){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const s=n(i(423)),a=n(i(980)),r=n(i(8659)),o=n(i(8541)),l=n(i(1427)),c=n(i(3875)),d=n(i(8078)),u=i(7997);class h{constructor(e){this.el=(0,u.createElement)("div","lm-Widget"),this._container=(0,u.createElement)("div","waveform"),this._duration=(0,u.createElement)("div","duration","0:00"),this._currentTime=(0,u.createElement)("div","time","0:00"),this._container.append(this._duration,this._currentTime),this.el.append(this._container),this._config=e}get url(){return this._config.isStreaming?this._pcmPlayer.url:(0,u.createObjectURL)(this._wavesurfer.getDecodedData())}set sampleRate(e){this._config.isStreaming&&(this._pcmPlayer.sampleRate=e),this._wavesurfer.options.sampleRate=e}load(e){this._config.isStreaming?(this._pcmPlayer.feed(e),this._wavesurfer.load(this.url)):this._wavesurfer.load(e)}setDone(){this._pcmPlayer.setDone()}createPCMPlayer(){this._config.isStreaming&&(this._pcmPlayer=new d.default({channels:1,sampleRate:this._config.options.sampleRate}),this.el.append(this._pcmPlayer.playButton))}createDownloadButton(){this._downloadButton=(0,u.createElement)("button","btn btn-success my-3");const e="zh"===this._config.language?"下载":"Download";this._downloadButton.innerHTML=`${e} <i class="fa fa-download"></i>`,this.el.append(this._downloadButton),this._downloadButton.onclick=()=>{const e=document.createElement("a");e.href=this.url,e.download="audio.wav",e.click()}}static createPlugins(e){var t;const i={hover:()=>{var t;return a.default.create(null===(t=e.pluginOptions)||void 0===t?void 0:t.hover)},minimap:()=>{var t,i;return r.default.create(Object.assign(Object.assign({},null===(t=e.pluginOptions)||void 0===t?void 0:t.minimap),{plugins:[a.default.create(Object.assign(Object.assign({},null===(i=e.pluginOptions)||void 0===i?void 0:i.hover),{lineWidth:1}))]}))},spectrogram:()=>{var t;return o.default.create(null===(t=e.pluginOptions)||void 0===t?void 0:t.spectrogram)},timeline:()=>{var t;return l.default.create(null===(t=e.pluginOptions)||void 0===t?void 0:t.timeline)},zoom:()=>{var t;return c.default.create(null===(t=e.pluginOptions)||void 0===t?void 0:t.zoom)}};return Array.from(null!==(t=e.plugins)&&void 0!==t?t:[]).map((e=>{var t;return null===(t=i[e])||void 0===t?void 0:t.call(i)})).filter(Boolean)}createWaveSurfer(){this._wavesurfer=s.default.create(Object.assign(Object.assign({},this._config.options),{container:this._container,plugins:h.createPlugins(this._config)})),this._wavesurfer.on("interaction",(()=>this._wavesurfer.playPause())),this._wavesurfer.on("decode",(e=>this._duration.textContent=(0,u.formatTime)(e))),this._wavesurfer.on("timeupdate",(e=>this._currentTime.textContent=(0,u.formatTime)(e)))}static create(e){const t=new h(e);return t.createWaveSurfer(),t.createPCMPlayer(),t.createDownloadButton(),t}}t.default=h}}]);