diff options
| author | Michael <michael.foiani@gmail.com> | 2022-06-10 15:41:38 -0400 |
|---|---|---|
| committer | Michael <michael.foiani@gmail.com> | 2022-06-10 15:41:38 -0400 |
| commit | 1688af3de54419029773fb85b78bca4500f7f0de (patch) | |
| tree | 73e777815eb2c6e91e0adb3c4702bb7ef2f7178d /src/client/views/nodes/RecordingBox | |
| parent | 3627d2597ffb52f00c3b82456b1b6693006c93fa (diff) | |
big bug problems with recording. some reason interacting with the canvas is making the recording inactive - i think :/
Diffstat (limited to 'src/client/views/nodes/RecordingBox')
| -rw-r--r-- | src/client/views/nodes/RecordingBox/ProgressBar.tsx | 8 | ||||
| -rw-r--r-- | src/client/views/nodes/RecordingBox/RecordingBox.tsx | 12 | ||||
| -rw-r--r-- | src/client/views/nodes/RecordingBox/RecordingView.tsx | 99 |
3 files changed, 70 insertions, 49 deletions
diff --git a/src/client/views/nodes/RecordingBox/ProgressBar.tsx b/src/client/views/nodes/RecordingBox/ProgressBar.tsx index 493069394..1bb2b7c84 100644 --- a/src/client/views/nodes/RecordingBox/ProgressBar.tsx +++ b/src/client/views/nodes/RecordingBox/ProgressBar.tsx @@ -161,12 +161,12 @@ export function ProgressBar(props: ProgressBarProps) { } // pointerdown event for the progress bar - const onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => { - // don't move the videobox element - e.stopPropagation() + const onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => { + // don't move the videobox element + e.stopPropagation(); // if recording, do nothing - if (props.recording) return; + if (props.recording) return; // get the segment the user clicked on to be dragged const clickedSegment = e.target as HTMLDivElement & EventTarget diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx index 5e97e3eb5..6fe67b6db 100644 --- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx @@ -8,8 +8,8 @@ import { FieldView } from "../FieldView"; import { VideoBox } from "../VideoBox"; import { RecordingView } from './RecordingView'; import { DocumentType } from "../../../documents/DocumentTypes"; -import { RecordingApi } from "../../../util/RecordingApi"; -import { Doc, FieldsSym } from "../../../../fields/Doc"; +import { Presentation } from "../../../util/RecordingApi"; +import { Doc } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; @@ -21,7 +21,7 @@ export class RecordingBox extends ViewBoxBaseComponent() { private _ref: React.RefObject<HTMLDivElement> = React.createRef(); constructor(props: any) { - super(props); + super(props); } componentDidMount() { @@ -38,7 +38,7 @@ export class RecordingBox extends ViewBoxBaseComponent() { } @action - setResult = (info: Upload.AccessPathInfo, trackScreen: boolean) => { + setResult = (info: Upload.AccessPathInfo, presentation?: Presentation) => { this.result = info this.dataDoc.type = DocumentType.VID; this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration; @@ -47,9 +47,7 @@ export class RecordingBox extends ViewBoxBaseComponent() { this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.client); this.dataDoc[this.fieldKey + "-recorded"] = true; // stringify the presenation and store it - if (trackScreen) { - this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear()); - } + presentation?.movements && (this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(presentation)); } render() { diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx index 138e72274..208eaf45a 100644 --- a/src/client/views/nodes/RecordingBox/RecordingView.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx @@ -8,16 +8,17 @@ import { IconContext } from "react-icons"; import { Networking } from '../../../Network'; import { Upload } from '../../../../server/SharedMediaTypes'; import { returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils'; -import { RecordingApi } from '../../../util/RecordingApi'; +import { Presentation, RecordingApi } from '../../../util/RecordingApi'; export interface MediaSegment { videoChunks: any[], endTime: number, - startTime: number + startTime: number, + presenation?: Presentation, } interface IRecordingViewProps { - setResult: (info: Upload.AccessPathInfo, trackScreen: boolean) => void + setResult: (info: Upload.AccessPathInfo, presentation?: Presentation) => void setDuration: (seconds: number) => void id: string } @@ -58,13 +59,18 @@ export function RecordingView(props: IRecordingViewProps) { sampleRate: 44100 } } + + useEffect(() => console.info('progess', progress), [progress]) useEffect(() => { - if (finished) { + if (finished) { + // make the total presentation that'll match the concatted video + const concatPres = trackScreen ? RecordingApi.Instance.concatPresentations(videos.map(v => v.presenation as Presentation)) : undefined; + // this async function uses the server to create the concatted video and then sets the result to it's accessPaths (async () => { - const videoFiles = videos.map((vid, i) => new File(vid.videoChunks, `segvideo${i}.mkv`, { type: vid.videoChunks[0].type, lastModified: Date.now() })); + const videoFiles = videos.map((vid, i) => new File(vid.videoChunks, `segvideo${i}.mkv`, { type: vid.videoChunks[0].type, lastModified: Date.now() })); // upload the segments to the server and get their server access paths const serverPaths: string[] = (await Networking.UploadFilesToServer(videoFiles)) @@ -72,7 +78,7 @@ export function RecordingView(props: IRecordingViewProps) { // concat the segments together using post call const result: Upload.AccessPathInfo | Error = await Networking.PostToServer('/concatVideos', serverPaths); - !(result instanceof Error) ? props.setResult(result, trackScreen) : console.error("video conversion failed"); + !(result instanceof Error) ? props.setResult(result, concatPres) : console.error("video conversion failed"); })(); } }, [videos]) @@ -133,53 +139,70 @@ export function RecordingView(props: IRecordingViewProps) { trackScreen && RecordingApi.Instance.start(); } - videoRecorder.current.onstop = () => { + videoRecorder.current.onstop = () => { + RecordingApi.Instance.stop(); // if we have a last portion - if (videoChunks.length > 1) { + if (videoChunks.length > 1) { // append the current portion to the video pieces - setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current, startTime: videos?.lastElement()?.endTime || 0 }]) + setVideos(videos => [...videos, { + videoChunks: videoChunks, + endTime: recordingTimerRef.current, + startTime: videos?.lastElement()?.endTime || 0, + // RecordingApi.stop() will return undefined if no track screen + presenation: RecordingApi.Instance.getPresentation() + }]) + // now that we got the presentation data, we can clear for the next segment to be recorded + RecordingApi.Instance.clear(); } - // reset the temporary chunks - videoChunks = [] - setRecording(false); - trackScreen && RecordingApi.Instance.pause(); + // reset the temporary chunks + videoChunks = [] + setRecording(false); } videoRecorder.current.start(200) } - const stop = (e: React.PointerEvent) => { - e.stopPropagation(); - if (videoRecorder.current) { - if (videoRecorder.current.state !== "inactive") { - videoRecorder.current.stop(); - } - - // this will call upon progessbar to update videos to be in the correct order - setFinished(true); - - // end the streams (audio/video) to remove recording icon - const stream = videoElementRef.current!.srcObject; - stream instanceof MediaStream && stream.getTracks().forEach(track => track.stop()); - } + const finish = (e: React.PointerEvent) => { + e.stopPropagation(); + console.log('finish', videoRecorder.current) + // if inactive, then we're done recording all the segments + if (videoRecorder.current && videoRecorder.current.state !== "inactive") { + console.log('stopping recorder', videoRecorder.current?.state) + + + + // call stop on the video recorder + videoRecorder.current?.stop(); + + // end the streams (audio/video) to remove recording icon + const stream = videoElementRef.current!.srcObject; + stream instanceof MediaStream && stream.getTracks().forEach(track => track.stop()); + + // clear the recoringApi - this is done in the stop method + // RecordingApi.Instance.clear(); + + // this will call upon progessbar to update videos to be in the correct order + console.log('setFinished to true', finished) + setFinished(true); + } } const pause = (e: React.PointerEvent) => { - e.stopPropagation() - if (videoRecorder.current) { - if (videoRecorder.current.state === "recording") { - videoRecorder.current.stop(); - } - } + e.stopPropagation() + // if recording, then this is just a new segment + videoRecorder.current?.state === "recording" && videoRecorder.current.stop(); } - const startOrResume = (e: React.PointerEvent) => { + const start = (e: React.PointerEvent) => { // the code to start or resume does not get triggered if we start dragging the button setupMoveUpEvents({}, e, returnTrue, returnFalse, e => { - (!videoRecorder.current || videoRecorder.current.state === "inactive") && record(); - return true; // cancels propagation to documentView to avoid selecting it. + if (!videoRecorder.current || videoRecorder.current.state === "inactive") { + record(); + // trackScreen && RecordingApi.Instance.start(); + } + return true; // cancels propagation to documentView to avoid selecting it. }, false, false); } @@ -218,7 +241,7 @@ export function RecordingView(props: IRecordingViewProps) { <div className="record-button-wrapper"> {recording ? <button className="stop-button" onPointerDown={pause} /> : - <button className="record-button" onPointerDown={startOrResume} /> + <button className="record-button" onPointerDown={start} /> } </div> @@ -229,7 +252,7 @@ export function RecordingView(props: IRecordingViewProps) { <MdBackspace onPointerDown={undoPrevious} /> </IconContext.Provider> <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}> - <FaCheckCircle onPointerDown={stop} /> + <FaCheckCircle onPointerDown={finish} /> </IconContext.Provider> </div> |
