@@ -66,6 +66,16 @@ public class VideoRecordingExample : MonoBehaviour
6666 /// </summary>
6767 public Toggle recordMicrophoneAudioToggle ;
6868
69+ /// <summary>
70+ /// The microphone frequency.
71+ /// </summary>
72+ public MicrophoneFrequencyPreset microphoneFrequency = MicrophoneFrequencyPreset . _48000 ;
73+
74+ /// <summary>
75+ /// The microphone frequency.
76+ /// </summary>
77+ public Dropdown microphoneFrequencyDropdown ;
78+
6979 [ Space ( 20 ) ]
7080
7181 /// <summary>
@@ -133,6 +143,14 @@ public class VideoRecordingExample : MonoBehaviour
133143
134144 int recordEveryNthFrame ;
135145
146+ int recordingWidth ;
147+ int recordingHeight ;
148+ int videoFramerate ;
149+ int audioSampleRate ;
150+ int audioChannelCount ;
151+ int videoBitrate ;
152+ float frameDuration ;
153+
136154 ComicFilter comicFilter ;
137155
138156 /// <summary>
@@ -165,7 +183,10 @@ void Start ()
165183
166184 // Update GUI state
167185 requestedResolutionDropdown . value = ( int ) requestedResolution ;
168- containerDropdown . value = ( int ) container - 1 ;
186+ containerDropdown . value = ( int ) container ;
187+ string [ ] enumNames = System . Enum . GetNames ( typeof ( MicrophoneFrequencyPreset ) ) ;
188+ int index = Array . IndexOf ( enumNames , microphoneFrequency . ToString ( ) ) ;
189+ microphoneFrequencyDropdown . value = index ;
169190 applyComicFilterToggle . isOn = applyComicFilter ;
170191 recordMicrophoneAudioToggle . isOn = recordMicrophoneAudio ;
171192 }
@@ -245,19 +266,24 @@ void Update ()
245266 comicFilter . Process ( rgbaMat , rgbaMat ) ;
246267
247268 if ( isVideoRecording ) {
248- Imgproc . putText ( rgbaMat , "[NatCorder With OpenCVForUnity Example]" , new Point ( 5 , rgbaMat . rows ( ) - 30 ) , Imgproc . FONT_HERSHEY_SIMPLEX , 0.5 , new Scalar ( 255 , 255 , 255 , 255 ) , 1 , Imgproc . LINE_AA , false ) ;
249- Imgproc . putText ( rgbaMat , "- Video Recording Example" , new Point ( 5 , rgbaMat . rows ( ) - 10 ) , Imgproc . FONT_HERSHEY_SIMPLEX , 0.5 , new Scalar ( 255 , 255 , 255 , 255 ) , 1 , Imgproc . LINE_AA , false ) ;
269+ Imgproc . putText ( rgbaMat , "[NatCorder With OpenCVForUnity Example]" , new Point ( 5 , rgbaMat . rows ( ) - 70 ) , Imgproc . FONT_HERSHEY_SIMPLEX , 0.5 , new Scalar ( 255 , 255 , 255 , 255 ) , 1 , Imgproc . LINE_AA , false ) ;
270+ Imgproc . putText ( rgbaMat , "- Video Recording Example" , new Point ( 5 , rgbaMat . rows ( ) - 50 ) , Imgproc . FONT_HERSHEY_SIMPLEX , 0.5 , new Scalar ( 255 , 255 , 255 , 255 ) , 1 , Imgproc . LINE_AA , false ) ;
271+ if ( container == ContainerPreset . MP4 || container == ContainerPreset . HEVC )
272+ {
273+ Imgproc . putText ( rgbaMat , "- [" + container + "] SIZE:" + recordingWidth + "x" + recordingHeight + " FPS:" + videoFramerate , new Point ( 5 , rgbaMat . rows ( ) - 30 ) , Imgproc . FONT_HERSHEY_SIMPLEX , 0.5 , new Scalar ( 255 , 255 , 255 , 255 ) , 1 , Imgproc . LINE_AA , false ) ;
274+ Imgproc . putText ( rgbaMat , "- ASR:" + audioSampleRate + " ACh:" + audioChannelCount + " VBR:" + videoBitrate + " MicFreq:" + ( int ) microphoneFrequency , new Point ( 5 , rgbaMat . rows ( ) - 10 ) , Imgproc . FONT_HERSHEY_SIMPLEX , 0.5 , new Scalar ( 255 , 255 , 255 , 255 ) , 1 , Imgproc . LINE_AA , false ) ;
275+ }
276+ else if ( container == ContainerPreset . GIF ) {
277+ Imgproc . putText ( rgbaMat , "- [" + container + "] SIZE:" + recordingWidth + "x" + recordingHeight + " FrameDur:" + frameDuration , new Point ( 5 , rgbaMat . rows ( ) - 30 ) , Imgproc . FONT_HERSHEY_SIMPLEX , 0.5 , new Scalar ( 255 , 255 , 255 , 255 ) , 1 , Imgproc . LINE_AA , false ) ;
278+ }
250279 }
251280
252281 // Restore the coordinate system of the image by OpenCV's Flip function.
253282 Utils . fastMatToTexture2D ( rgbaMat , texture ) ;
254283
255284 // Record frames
256285 if ( videoRecorder != null && isVideoRecording && frameCount ++ % recordEveryNthFrame == 0 ) {
257- // Blit to recording frame
258- var frame = videoRecorder . AcquireFrame ( ) ;
259- Graphics . Blit ( texture , frame ) ;
260- videoRecorder . CommitFrame ( frame , recordingClock . Timestamp ) ;
286+ videoRecorder . CommitFrame ( ( IntPtr ) rgbaMat . dataAddr ( ) , recordingClock . Timestamp ) ;
261287 }
262288 }
263289
@@ -272,42 +298,56 @@ private void StartRecording ()
272298 return ;
273299
274300 Debug . Log ( "StartRecording ()" ) ;
275- if ( fpsMonitor != null ) {
276- fpsMonitor . consoleText = "Recording" ;
277- }
278-
279- // First make sure recording microphone is only on MP4
280- recordMicrophoneAudio &= container == ContainerPreset . MP4 ;
301+
302+ // First make sure recording microphone is only on MP4 or HEVC
303+ recordMicrophoneAudio = recordMicrophoneAudioToggle . isOn ;
304+ recordMicrophoneAudio &= ( container == ContainerPreset . MP4 || container == ContainerPreset . HEVC ) ;
281305 // Create recording configurations
282- int recordingWidth = webCamTextureToMatHelper . GetWidth ( ) ;
283- int recordingHeight = webCamTextureToMatHelper . GetHeight ( ) ;
306+ recordingWidth = webCamTextureToMatHelper . GetWidth ( ) ;
307+ recordingHeight = webCamTextureToMatHelper . GetHeight ( ) ;
308+ videoFramerate = 30 ;
309+ audioSampleRate = recordMicrophoneAudio ? AudioSettings . outputSampleRate : 0 ;
310+ audioChannelCount = recordMicrophoneAudio ? ( int ) AudioSettings . speakerMode : 0 ;
311+ videoBitrate = ( int ) ( 960 * 540 * 11.4f ) ;
312+ frameDuration = 0.1f ;
284313
285314 // Start recording
286315 recordingClock = new RealtimeClock ( ) ;
287316 if ( container == ContainerPreset . MP4 ) {
288317 videoRecorder = new MP4Recorder (
289318 recordingWidth ,
290319 recordingHeight ,
291- 30 ,
292- recordMicrophoneAudio ? AudioSettings . outputSampleRate : 0 ,
293- recordMicrophoneAudio ? ( int ) AudioSettings . speakerMode : 0 ,
320+ videoFramerate ,
321+ audioSampleRate ,
322+ audioChannelCount ,
294323 OnVideo
295324 ) ;
296325 recordEveryNthFrame = 1 ;
297- } else {
326+ } else if ( container == ContainerPreset . HEVC ) {
327+ videoRecorder = new HEVCRecorder (
328+ recordingWidth ,
329+ recordingHeight ,
330+ videoFramerate ,
331+ audioSampleRate ,
332+ audioChannelCount ,
333+ OnVideo
334+ ) ;
335+ recordEveryNthFrame = 1 ;
336+ } else if ( container == ContainerPreset . GIF ) {
298337 videoRecorder = new GIFRecorder (
299338 recordingWidth ,
300339 recordingHeight ,
301- 0.1f ,
340+ frameDuration ,
302341 OnVideo
303342 ) ;
304343 recordEveryNthFrame = 5 ;
305344 }
306345 frameCount = 0 ;
346+
307347 // Start microphone and create audio input
308348 if ( recordMicrophoneAudio ) {
309349 StartMicrophone ( ) ;
310- audioInput = AudioInput . Create ( videoRecorder , microphoneSource , recordingClock , true ) ;
350+ audioInput = new AudioInput ( videoRecorder , recordingClock , microphoneSource , true ) ;
311351 }
312352
313353 StartCoroutine ( "Countdown" ) ;
@@ -323,7 +363,7 @@ private void StartMicrophone ()
323363 {
324364 #if ! UNITY_WEBGL || UNITY_EDITOR // No `Microphone` API on WebGL :(
325365 // Create a microphone clip
326- microphoneSource . clip = Microphone . Start ( null , true , 60 , 48000 ) ;
366+ microphoneSource . clip = Microphone . Start ( null , true , ( int ) MAX_RECORDING_TIME , ( int ) microphoneFrequency ) ;
327367 while ( Microphone . GetPosition ( null ) <= 0 )
328368 ;
329369 // Play through audio source
@@ -373,9 +413,15 @@ private IEnumerator Countdown ()
373413 float startTime = Time . time ;
374414 while ( ( Time . time - startTime ) < MAX_RECORDING_TIME ) {
375415
376- if ( fpsMonitor != null ) {
377- fpsMonitor . consoleText += "." ;
378- }
416+ if ( fpsMonitor != null )
417+ {
418+ string str = "Recording" ;
419+ for ( int i = 0 ; i < ( int ) ( MAX_RECORDING_TIME - ( Time . time - startTime ) ) ; i ++ )
420+ {
421+ str += "." ;
422+ }
423+ fpsMonitor . consoleText = str ;
424+ }
379425
380426 yield return new WaitForSeconds ( 0.5f ) ;
381427 }
@@ -409,7 +455,6 @@ private void PlayVideo (string path)
409455
410456 videoPlayer . source = VideoSource . Url ;
411457 videoPlayer . url = path ;
412-
413458 videoPlayer . audioOutputMode = VideoAudioOutputMode . AudioSource ;
414459 videoPlayer . controlledAudioTrackCount = 1 ;
415460 videoPlayer . EnableAudioTrack ( 0 , true ) ;
@@ -464,7 +509,9 @@ private void StopVideo ()
464509
465510 private void ShowAllVideoUI ( )
466511 {
512+ requestedResolutionDropdown . interactable = true ;
467513 containerDropdown . interactable = true ;
514+ microphoneFrequencyDropdown . interactable = true ;
468515 applyComicFilterToggle . interactable = true ;
469516 recordMicrophoneAudioToggle . interactable = true ;
470517 recordVideoButton . interactable = true ;
@@ -477,7 +524,9 @@ private void ShowAllVideoUI ()
477524
478525 private void HideAllVideoUI ( )
479526 {
527+ requestedResolutionDropdown . interactable = false ;
480528 containerDropdown . interactable = false ;
529+ microphoneFrequencyDropdown . interactable = false ;
481530 applyComicFilterToggle . interactable = false ;
482531 recordMicrophoneAudioToggle . interactable = false ;
483532 recordVideoButton . interactable = false ;
@@ -559,9 +608,28 @@ public void OnRequestedResolutionDropdownValueChanged (int result)
559608 /// </summary>
560609 public void OnContainerDropdownValueChanged ( int result )
561610 {
562- Debug . Log ( result ) ;
563- if ( ( int ) container != result + 1 ) {
564- container = ( ContainerPreset ) ( result + 1 ) ;
611+ if ( ( int ) container != result ) {
612+ container = ( ContainerPreset ) ( result ) ;
613+ }
614+
615+ #if UNITY_WEBGL && ! UNITY_EDITOR
616+ // WebGL platform only supports MP4 format.
617+ containerDropdown . value = ( int ) ContainerPreset . MP4 ;
618+ container = ContainerPreset . MP4 ;
619+ #endif
620+ }
621+
622+ /// <summary>
623+ /// Raises the microphone frequency dropdown value changed event.
624+ /// </summary>
625+ public void OnMicrophoneFrequencyDropdownValueChanged ( int result )
626+ {
627+ string [ ] enumNames = Enum . GetNames ( typeof ( MicrophoneFrequencyPreset ) ) ;
628+ int value = ( int ) System . Enum . Parse ( typeof ( MicrophoneFrequencyPreset ) , enumNames [ result ] , true ) ;
629+
630+ if ( ( int ) microphoneFrequency != value )
631+ {
632+ microphoneFrequency = ( MicrophoneFrequencyPreset ) value ;
565633 }
566634 }
567635
@@ -620,8 +688,10 @@ public void OnPlayVideoButtonClick ()
620688 // Playback the video
621689 #if UNITY_IOS
622690 PlayVideo ( "file://" + videoPath ) ;
691+ #elif UNITY_WEBGL
692+ Debug . Log ( "Please open the video URL (" + videoPath + ") in a new browser tab." ) ;
623693 #else
624- PlayVideo ( videoPath ) ;
694+ PlayVideo ( videoPath ) ;
625695 #endif
626696 }
627697
@@ -712,8 +782,18 @@ private void Dimensions (ResolutionPreset preset, out int width, out int height)
712782
713783 public enum ContainerPreset
714784 {
715- MP4 = 1 ,
716- GIF
785+ MP4 ,
786+ HEVC ,
787+ GIF ,
788+ }
789+
790+ public enum MicrophoneFrequencyPreset
791+ {
792+ _16000 = 16000 ,
793+ _24000 = 24000 ,
794+ _32000 = 32000 ,
795+ _44100 = 44100 ,
796+ _48000 = 48000 ,
717797 }
718798 }
719799}
0 commit comments