|
110 | 110 | <div id="chkCanvas" style="display:none;padding:5px;background-color:gainsboro;border-radius:20px;padding-left:15px;padding-right:15px;margin-right:10px;">🔴 Canvas</div> |
111 | 111 | </div> |
112 | 112 | <div id="mockHolder"></div> |
113 | | - <div> |
| 113 | + <div id="recordHolder"> |
114 | 114 | <Component id="mic_holder"></Component> |
115 | 115 | <Component id="mic_holder2"></Component> |
116 | 116 | <Component id="camera_holder"></Component> |
117 | 117 | <canvas id="canvas_screen"></canvas> |
118 | 118 | </div> |
| 119 | + |
119 | 120 | <div id="playholder" style="display:none;"> |
| 121 | + <div>🔵 Last Record</div> |
120 | 122 | <video id="playscreen"></video> |
121 | 123 | <Component id="playaudio"></Component> |
122 | 124 | </div> |
|
155 | 157 | }, |
156 | 158 | stream : null, |
157 | 159 | tracks : [], |
| 160 | + recordType : "none", |
158 | 161 | video : { |
159 | 162 | mode : "none" |
160 | 163 | }, |
|
190 | 193 | } |
191 | 194 | //canvas |
192 | 195 |
|
193 | | -canvas_screen.el.style.display = "none"; |
| 196 | + |
194 | 197 |
|
195 | 198 | canvas_screen.el.style.width = "640px"; |
196 | 199 | canvas_screen.el.style.height = "480px"; |
|
215 | 218 | ctx.fill(); |
216 | 219 |
|
217 | 220 | var cstate = 0; |
218 | | - |
219 | | - |
220 | 221 | btnNext.el.addEventListener("click",()=>{ |
221 | 222 | switch(cstate%3) { |
222 | 223 | case 0: |
|
270 | 271 | } |
271 | 272 | cstate++; |
272 | 273 | }) |
| 274 | +canvas_screen.el.style.display = "none"; |
273 | 275 |
|
274 | 276 |
|
| 277 | +var cstate1 = 0; |
| 278 | +setInterval(()=>{ // like ping, to record something even if is a picture |
| 279 | + if(self.app.video.mode == "canvas" || self.app.video.mode == "play") { |
| 280 | + //console.log("OK"); |
| 281 | + if(cstate1==0) { |
| 282 | + ctx.fillStyle = "#000"; |
| 283 | + ctx.strokeStyle = "#00f"; |
| 284 | + ctx.beginPath(); |
| 285 | + ctx.moveTo(0, 479); |
| 286 | + ctx.lineTo(639, 479); |
| 287 | + ctx.closePath(); |
| 288 | + ctx.stroke(); |
| 289 | + cstate1 = 1; |
| 290 | + } else if(cstate1==1) { |
| 291 | + ctx.fillStyle = "#001"; |
| 292 | + ctx.strokeStyle = "#f00"; |
| 293 | + ctx.beginPath(); |
| 294 | + ctx.moveTo(0, 479); |
| 295 | + ctx.lineTo(479, 639); |
| 296 | + ctx.closePath(); |
| 297 | + ctx.stroke(); |
| 298 | + cstate1 = 0; |
| 299 | + } |
| 300 | + } |
| 301 | +},10); |
| 302 | + |
275 | 303 | // devices |
276 | | -self.app.stream = stream = canvas_screen.el.captureStream(32); // frames per second |
| 304 | +//self.app.stream = stream = canvas_screen.el.captureStream(32); // frames per second |
| 305 | +var stream = null; |
| 306 | +self.app.stream = null; |
| 307 | + |
277 | 308 |
|
278 | 309 | let audioStream0 = null; |
279 | 310 |
|
|
388 | 419 | chkCanvas.el.style.display = "none"; |
389 | 420 | chkCamera.el.style.display = ""; |
390 | 421 |
|
| 422 | + if(self.app.video.mode == "play") { |
| 423 | + recordHolder.el.style.display = ""; |
| 424 | + playscreen.el.style.display = "none"; |
| 425 | + } |
391 | 426 | self.app.video.mode = "camera"; |
392 | 427 |
|
393 | 428 | canvas_screen.el.style.display = "none"; |
|
413 | 448 |
|
414 | 449 | btnSetCanvas.el.addEventListener("click",()=>{ |
415 | 450 |
|
| 451 | + // CANVAS WILL NOT RECORD FIRST FRAME IF YOU DOWN CHANGE THE CONTENT OF CANVAS AT LEAST ONE TIME |
| 452 | + |
416 | 453 | chkScreen.el.style.display = "none"; |
417 | 454 | chkCanvas.el.style.display = ""; |
418 | 455 | chkCamera.el.style.display = "none"; |
419 | 456 |
|
420 | | - self.app.video.mode = "canvas"; |
421 | | - if(cameraDevice) { |
| 457 | + |
| 458 | + if(cameraDevice) { // stop camera and screen |
| 459 | + console.log("CLEAR camera"); |
422 | 460 | cameraDevice.pause(); |
423 | 461 | stream.getTracks().forEach(function(track) { |
424 | 462 | track.stop(); |
425 | 463 | }); |
426 | 464 | cameraDevice.style.display = "none"; |
427 | 465 | camera_holder.$.elementsClear(); |
428 | 466 | } |
| 467 | + |
| 468 | + if(self.app.video.mode == "play") { |
| 469 | + recordHolder.el.style.display = ""; |
| 470 | + playscreen.el.style.display = "none"; |
| 471 | + } |
| 472 | + self.app.video.mode = "canvas"; |
429 | 473 | canvas_screen.el.style.display = ""; |
430 | | - stream = canvas_screen.el.captureStream(32); |
| 474 | + self.app.stream = stream = canvas_screen.el.captureStream(32); |
| 475 | + |
| 476 | + |
| 477 | + console.log(stream); |
431 | 478 |
|
432 | 479 | }); |
433 | 480 |
|
|
437 | 484 | chkCamera.el.style.display = "none"; |
438 | 485 |
|
439 | 486 | canvas_screen.el.style.display = "none"; |
440 | | - self.app.video.mode = "desktop"; |
| 487 | + |
441 | 488 |
|
442 | 489 | if(cameraDevice) { |
443 | 490 | cameraDevice.pause(); |
|
448 | 495 | camera_holder.$.elementsClear(); |
449 | 496 | } |
450 | 497 |
|
| 498 | + if(self.app.video.mode == "play") { |
| 499 | + recordHolder.el.style.display = ""; |
| 500 | + playscreen.el.style.display = "none"; |
| 501 | + } |
| 502 | + self.app.video.mode = "desktop"; |
| 503 | + |
451 | 504 |
|
452 | 505 | const constraints = { |
453 | 506 | video: { |
|
478 | 531 | } catch (error) { |
479 | 532 | stream = schema.el.control.src = window.URL.createObjectURL(stream2); |
480 | 533 | } |
| 534 | + |
| 535 | + stream.getTracks().forEach((track)=>{ |
| 536 | + track.onended = function(event) { |
| 537 | + log("end of screen capture"); |
| 538 | + chkScreen.el.style.display = "none"; |
| 539 | + stopRecording(); |
| 540 | + } |
| 541 | + }); |
| 542 | + |
481 | 543 | schema.el.control.play(); |
482 | 544 | cameraDevice = schema.el.control; |
483 | 545 | }); |
|
487 | 549 | chkCanvas.el.style.display = "none"; |
488 | 550 | chkCamera.el.style.display = "none"; |
489 | 551 |
|
| 552 | + |
490 | 553 | if(cameraDevice) { |
491 | 554 | cameraDevice.pause(); |
492 | 555 | stream.getTracks().forEach(function(track) { |
|
495 | 558 | cameraDevice.style.display = "none"; |
496 | 559 | camera_holder.$.elementsClear(); |
497 | 560 | } |
| 561 | + |
| 562 | + if(self.app.video.mode == "play") { |
| 563 | + recordHolder.el.style.display = ""; |
| 564 | + playscreen.el.style.display = "none"; |
| 565 | + } |
| 566 | + |
498 | 567 | self.app.video.mode = "none"; |
499 | 568 | camera_holder.$.elementsClear(); |
500 | 569 | playscreen.el.style.display = "none"; |
|
540 | 609 | function handleDataAvailable(event) { |
541 | 610 |
|
542 | 611 | if (event.data && event.data.size > 0) { |
| 612 | + console.log(event.data); |
543 | 613 | recordedBlobs.push(event.data); |
544 | 614 | } else { |
545 | 615 | //console.log( mediaRecorder.requestData() ); |
546 | 616 | //console.log(event); |
547 | 617 | } |
548 | 618 | } |
549 | 619 |
|
| 620 | +async function handlePause(event) { |
| 621 | + log('Recorder paused: ', event); |
| 622 | +} |
550 | 623 | async function handleStop(event) { |
551 | 624 | log('Recorder stopped: ', event); |
| 625 | + |
552 | 626 | if(self.app.video.mode == "none") { |
553 | 627 | const superBuffer = new Blob(recordedBlobs, {type: 'audio/webm'}); |
554 | | - |
555 | 628 | var url = (window.URL || window.webkitURL).createObjectURL(superBuffer); |
556 | | - |
557 | 629 | var schema = await playaudio.$.elementSetPacketAsync(` |
558 | 630 | <audio id="audio" controls> |
559 | 631 | <source src="`+url+`" type="audio/webm"> |
560 | 632 | Your browser does not support the audio tag. |
561 | 633 | </audio> |
562 | 634 | `); |
563 | | - |
564 | 635 | self.app.audio.control = schema.el.audio; |
565 | | - |
566 | 636 | self.app.events.off("hitTrack",self.app.events.hitTrack); |
567 | 637 | delete self.app.events.hitTrack; |
568 | | - |
569 | 638 | } else { |
570 | 639 | const superBuffer = new Blob(recordedBlobs, {type: 'video/webm'}); |
571 | 640 | playscreen.el.src = window.URL.createObjectURL(superBuffer); |
|
583 | 652 | throw new Error("(you must select some input device)"); |
584 | 653 | return; |
585 | 654 | } |
586 | | - |
| 655 | + console.log("video mode",self.app.video.mode) |
| 656 | + console.log("audio mode",self.app.audio.mode) |
| 657 | + recordHolder.el.style.display = ""; |
587 | 658 | recordedBlobs = []; |
588 | 659 |
|
| 660 | + |
589 | 661 | var audioCtx = new AudioContext(); |
590 | 662 | var audioMixer = audioCtx.createMediaStreamDestination(); |
591 | 663 |
|
|
612 | 684 | } |
613 | 685 | console.log("hit",self.app.tracks[n]); |
614 | 686 | }; |
615 | | - //playback.start(); |
616 | 687 | self.app.events.on("hitTrack",self.app.events.hitTrack); |
617 | 688 |
|
| 689 | + // null signal to record empty audio space if mic is not activated |
| 690 | + var nullSignal = audioCtx.createOscillator(); |
| 691 | + nullSignal.type = 'sine'; |
| 692 | + nullSignal.frequency.value = 440; |
| 693 | + var nullSignalGain = audioCtx.createGain(); |
| 694 | + nullSignalGain.gain.value = -100; |
| 695 | + nullSignalGain.connect(audioMixer); |
618 | 696 | } |
619 | 697 |
|
620 | 698 | // mixing audio and video |
|
623 | 701 | .getAudioTracks() |
624 | 702 | .forEach((audioTrack) => stream.addTrack(audioTrack)); |
625 | 703 | } |
| 704 | + |
| 705 | + if(self.app.video.mode != "none") { |
| 706 | + self.app.recordType = "video"; |
| 707 | + } else { |
| 708 | + self.app.recordType = "audio"; |
| 709 | + } |
626 | 710 |
|
627 | 711 | var options = {}; |
628 | | - if(self.app.video.mode != "none") { |
| 712 | + if(self.app.recordType == "video") { |
| 713 | + |
| 714 | + console.log("VIDEO RECORD TYPE"); |
629 | 715 | options.mimeType = 'video/webm'; |
630 | 716 | try { |
631 | 717 | mediaRecorder = new MediaRecorder(stream, options); |
|
670 | 756 | btnPlay.el.disabled = true; |
671 | 757 | btnDownloadMovie.el.disabled = true; |
672 | 758 | mediaRecorder.onstop = handleStop; |
| 759 | + mediaRecorder.onpause = handlePause; |
673 | 760 | mediaRecorder.ondataavailable = handleDataAvailable; |
674 | 761 | mediaRecorder.onerror = function(error) { |
675 | 762 | console.log(error.name); |
676 | 763 | console.log(error); |
677 | 764 | } |
678 | | - |
679 | | - |
680 | 765 | mediaRecorder.start(); |
681 | | - |
682 | | - |
| 766 | + try { |
| 767 | + |
| 768 | + } catch(e) { |
| 769 | + log("error on media recorder start"); |
| 770 | + log(e.message); |
| 771 | + } |
683 | 772 |
|
684 | 773 |
|
685 | 774 | log('MediaRecorder started' + mediaRecorder); |
686 | 775 | } |
687 | 776 |
|
688 | 777 | function stopRecording() { |
689 | | - mediaRecorder.stop(); |
| 778 | + if(mediaRecorder.state != "inactive") { |
| 779 | + mediaRecorder.stop(); |
| 780 | + } else { // user stopped sharing screen. |
| 781 | + self.app.video.mode = "none"; |
| 782 | + chkScreen.el.style.display = "none"; |
| 783 | + } |
690 | 784 | log('Recorded Blobs: '+ recordedBlobs.length); |
691 | 785 | playscreen.el.controls = true; |
692 | 786 | } |
|
707 | 801 |
|
708 | 802 | btnRecord.el.addEventListener("click",()=>{ toggleRecording(); }); |
709 | 803 | btnPlay.el.addEventListener("click",()=>{ |
710 | | - playholder.el.style.display = ""; |
711 | | - |
712 | | - |
713 | | - if(cameraDevice) { |
714 | | - cameraDevice.pause(); |
715 | | - stream.getTracks().forEach(function(track) { |
716 | | - track.stop(); |
717 | | - }); |
718 | | - cameraDevice.style.display = "none"; |
719 | | - camera_holder.$.elementsClear(); |
720 | | - } |
721 | | - camera_holder.$.elementsClear(); |
722 | 804 |
|
723 | | - canvas_screen.el.style.display = "none"; |
724 | | - |
725 | | - if(self.app.video.mode == "none") { |
| 805 | + playholder.el.style.display = ""; |
| 806 | + recordHolder.el.style.display = "none"; |
| 807 | + if(self.app.recordType == "audio") { |
726 | 808 | playscreen.el.style.display = "none"; |
727 | 809 | self.app.audio.control.play(); |
728 | | - } else { |
| 810 | + self.app.audio.mode = "play"; |
| 811 | + } else if(self.app.recordType == "video") { |
729 | 812 | playscreen.el.style.display = ""; |
730 | 813 | playaudio.$.elementsClear(); |
731 | 814 | playscreen.el.style.width = "100%"; |
732 | 815 | playscreen.el.play(); |
| 816 | + self.app.video.mode = "play"; |
733 | 817 | } |
734 | 818 | }); |
735 | 819 | btnDownloadMovie.el.addEventListener("click",()=>{ download(); }); |
|
0 commit comments