diff options
author | bob <bcz@cs.brown.edu> | 2020-03-04 18:20:46 -0500 |
---|---|---|
committer | bob <bcz@cs.brown.edu> | 2020-03-04 18:20:46 -0500 |
commit | 26c973ecb47de86d94c39d71ad00ece38a85d623 (patch) | |
tree | ab67826925f435b2da5753fa537b317ef067c8af /src/client/views/nodes/AudioBox.tsx | |
parent | 85a95c5fdb5e34461ae9892b4f1cac426b7d667b (diff) |
changed text sampling to marking every second to get audio to synchronize better
Diffstat (limited to 'src/client/views/nodes/AudioBox.tsx')
-rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index c4c6365e3..e2002a596 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -17,6 +17,8 @@ import { ContextMenu } from "../ContextMenu"; import { Id } from "../../../new_fields/FieldSymbols"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { DocumentView } from "./DocumentView"; +import { Docs } from "../../documents/Documents"; +import { ComputedField } from "../../../new_fields/ScriptField"; interface Window { MediaRecorder: MediaRecorder; @@ -45,12 +47,15 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume _recorder: any; _recordStart = 0; + public static START = 0; @observable private static _scrubTime = 0; - @observable private _audioState: "unrecorded" | "recording" | "recorded" = "unrecorded"; - public static SetScrubTime = action((timeInMillisFrom1970: number) => AudioBox._scrubTime = timeInMillisFrom1970); + @computed get audioState(): undefined | "recording" | "paused" | "playing" { return this.dataDoc.audioState as (undefined | "recording" | "paused" | "playing"); } + set audioState(value) { this.dataDoc.audioState = value; } + public static SetScrubTime = (timeInMillisFrom1970: number) => { runInAction(() => AudioBox._scrubTime = 0); runInAction(() => AudioBox._scrubTime = timeInMillisFrom1970); }; public static ActiveRecordings: Doc[] = []; @computed get recordingStart() { return Cast(this.dataDoc[this.props.fieldKey + "-recordingStart"], DateField)?.date.getTime(); } + async slideTemplate() { return (await Cast((await Cast(Doc.UserDoc().slidesBtn, Doc) as Doc).dragFactory, Doc) as Doc); } componentWillUnmount() { this._reactionDisposer?.(); @@ -58,7 +63,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume this._scrubbingDisposer?.(); } componentDidMount() { - runInAction(() => this._audioState = this.path ? "recorded" : "unrecorded"); + runInAction(() => this.audioState = this.path ? "paused" : undefined); this._linkPlayDisposer = reaction(() => this.layoutDoc.scrollToLinkID, scrollLinkId => { if (scrollLinkId) { @@ -73,13 +78,14 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume selected => { const sel = selected.length ? selected[0].props.Document : undefined; this.Document.playOnSelect && this.recordingStart && sel && !Doc.AreProtosEqual(sel, this.props.Document) && this.playFromTime(DateCast(sel.creationDate).date.getTime()); + this.Document.playOnSelect && this.recordingStart && !sel && this.pause(); }); this._scrubbingDisposer = reaction(() => AudioBox._scrubTime, (time) => this.Document.playOnSelect && this.playFromTime(AudioBox._scrubTime)); } timecodeChanged = () => { const htmlEle = this._ele; - if (this._audioState === "recorded" && htmlEle) { + if (this.audioState !== "recording" && htmlEle) { htmlEle.duration && htmlEle.duration !== Infinity && runInAction(() => this.dataDoc.duration = htmlEle.duration); DocListCast(this.dataDoc.links).map(l => { let la1 = l.anchor1 as Doc; @@ -98,7 +104,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume pause = action(() => { this._ele!.pause(); - this.props.Document._audioState = "paused"; + this.audioState = "paused"; }); playFromTime = (absoluteTime: number) => { @@ -107,11 +113,15 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume playFrom = (seekTimeInSeconds: number) => { if (this._ele && AudioBox.Enabled) { if (seekTimeInSeconds < 0) { - this.pause(); + if (seekTimeInSeconds > -1) { + setTimeout(() => this.playFrom(0), -seekTimeInSeconds * 1000); + } else { + this.pause(); + } } else if (seekTimeInSeconds <= this._ele.duration) { this._ele.currentTime = seekTimeInSeconds; this._ele.play(); - runInAction(() => this.props.Document._audioState = "playing"); + runInAction(() => this.audioState = "playing"); } else { this.pause(); } @@ -120,7 +130,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume updateRecordTime = () => { - if (this._audioState === "recording") { + if (this.audioState === "recording") { setTimeout(this.updateRecordTime, 30); this.Document.currentTimecode = (new Date().getTime() - this._recordStart) / 1000; } @@ -135,6 +145,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume gumStream = stream; self._recorder = new MediaRecorder(stream); self.dataDoc[self.props.fieldKey + "-recordingStart"] = new DateField(new Date()); + AudioBox.START = new DateField(new Date()).date.getTime(); AudioBox.ActiveRecordings.push(self.props.Document); self._recorder.ondataavailable = async function (e: any) { const formData = new FormData(); @@ -151,8 +162,9 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume self.props.Document[self.props.fieldKey] = new AudioField(url); }); }; - runInAction(() => self._audioState = "recording"); self._recordStart = new Date().getTime(); + console.log("RECORD START = " + self._recordStart); + runInAction(() => self.audioState = "recording"); setTimeout(self.updateRecordTime, 0); self._recorder.start(); setTimeout(() => { @@ -172,7 +184,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume stopRecording = action(() => { this._recorder.stop(); this.dataDoc.duration = (new Date().getTime() - this._recordStart) / 1000; - this._audioState = "recorded"; + this.audioState = "paused"; const ind = AudioBox.ActiveRecordings.indexOf(this.props.Document); ind !== -1 && (AudioBox.ActiveRecordings.splice(ind, 1)); }); @@ -189,8 +201,19 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume e.stopPropagation(); } onStop = (e: any) => { - this.pause(); - this._ele!.currentTime = 0; + this.Document.playOnSelect = !this.Document.playOnSelect; + e.stopPropagation(); + } + onFile = (e: any) => { + const newDoc = Docs.Create.TextDocument("", { + title: "", _chromeStatus: "disabled", + x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y) + NumCast(this.props.Document._height) + 10, + _width: NumCast(this.props.Document._width), _height: 3 * NumCast(this.props.Document._height) + }); + Doc.GetProto(newDoc).recordingSource = this.dataDoc; + Doc.GetProto(newDoc).recordingStart = 0; + Doc.GetProto(newDoc).audioState = ComputedField.MakeFunction("this.recordingSource.audioState"); + this.props.addDocument?.(newDoc); e.stopPropagation(); } @@ -218,21 +241,26 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume const interactive = this.active() ? "-interactive" : ""; return <div className={`audiobox-container`} onContextMenu={this.specificContextMenu} onClick={!this.path ? this.recordClick : undefined}> - <div className="audiobox-handle" style={{ backgroundColor: this._audioState === "recording" ? "green" : undefined }} /> {!this.path ? - <button className={`audiobox-record${interactive}`} style={{ backgroundColor: this._audioState === "recording" ? "red" : "black" }}> - {this._audioState === "recording" ? "STOP" : "RECORD"} - </button> : + <div style={{ display: "flex", width: "100%", alignItems: "center" }}> + <div className="audiobox-playhead" style={{ alignItems: "center", display: "inherit", background: "dimgray" }} onClick={this.onFile}> + <FontAwesomeIcon style={{ width: "30px", background: this.Document.playOnSelect ? "yellow" : "dimGray" }} icon="file-alt" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> + </div> + <button className={`audiobox-record${interactive}`} style={{ position: "relative", backgroundColor: this.audioState === "recording" ? "red" : "black" }}> + {this.audioState === "recording" ? "STOP" : "RECORD"} + </button> + </div> : <div className="audiobox-controls"> <div className="audiobox-player" onClick={this.onPlay}> - <div className="audiobox-playhead"> <FontAwesomeIcon style={{ width: "100%" }} icon={this.props.Document._audioState === "paused" ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> - <div className="audiobox-playhead" onClick={this.onStop}><FontAwesomeIcon style={{ width: "100%" }} icon="stop" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> + <div className="audiobox-playhead"> <FontAwesomeIcon style={{ width: "100%" }} icon={this.audioState === "paused" ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> + <div className="audiobox-playhead" onClick={this.onStop}><FontAwesomeIcon style={{ width: "100%", background: this.Document.playOnSelect ? "yellow" : "dimGray" }} icon="hand-point-left" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> <div className="audiobox-timeline" onClick={e => e.stopPropagation()} onPointerDown={e => { if (e.button === 0 && !e.ctrlKey) { const rect = (e.target as any).getBoundingClientRect(); + const wasPaused = this.audioState === "paused"; this._ele!.currentTime = this.Document.currentTimecode = (e.clientX - rect.x) / rect.width * NumCast(this.dataDoc.duration); - this.pause(); + wasPaused && this.pause(); e.stopPropagation(); } }} > |