B4A Library AndroidVideoCapture - video recorder that is 100% embedded in B4A (6 Jan - new Lib Files in post 48)

The attached project is based on this project (click here). I was asked by @Mashiane to wrap it so that it can be used as a 100% standalone video recorder in B4A. It uses a custom view as the video view. The following applies to the project as it stands at present:

(Read the following and take note of especially point #2 about the folder that you need to create else the app will crash)

1. It can only be used in landscape mode
2. It stores the video files in folder /sdcard/Videos/*.mp4 - there is by default no such directory in the root folder so either create it manually or else add code in the B4A project to check if it exists and if not then create it via B4A code (sure it can be found somewhere on the forum)
3. The Zoom In and Zoom out functions can probably be controlled via a slider...but for this exercise I have added two buttons (Zoom In and Zoom Out)
4. There are a vast number of options as far as specifying video quality is concerned. I have not tested them all - as a matter of fact, I have only tested 2! So, try them and see if there is a difference.
5. The flash light can be switched in two ways (and they also work in conjunction with one another):
a. touch the view while the video recording is active
b. use the "Toggle Flash" button​
6. You will need to add some code to the B4A project to refresh the media files on you device else you will not see the recorded video in the /Videos folder - unless you disconnect your device and reconnect it again (in which case it will then show). Search the forum for how to do the refresh.
7. Take note of the permissions added to the B4A manifest files (some are not required)
I will play around with the code and post updates if and when I have figured out any other useful attributes to add.

Posting the following:
1. B4A project demonstrating the use of the video recorder
2. B4A library files - copy them to your additional library folder.

B4A project launched:
1.png



Video recording started:
2.png



Zoomed In:
3.png


Flash switched on:
4.png



Sample Code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: AndroidVideoCapture
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: landscape
    #CanInstallToExternalStorage: False
    'http://android-er.blogspot.co.za/2011/10/simple-exercise-of-video-capture-using.html

#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.


 
    Private b1, b2, b3, b4 As Button
    Private avc1 As AndroidVideoCapture

End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")
 
    avc1.MaximimDuration = 120000
    avc1.MaximumFileSize = 10000000
 
    'The video files will be stored in folder /sdcard/Videos/ of your device.
    'Add code to create this folder if the folder does not exist or else just create it manually
    avc1.VideoName = "video1"    'the video will now be stored as "video1.MP4"  
 
    avc1.VideoQuality = avc1.QUALITY_LOW    
 
 
 
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
 
    avc1.releaseResources

End Sub


Sub b1_Click
 
    avc1.setStartStopRecording
 
End Sub

Sub avc1_flash_toggled (flashOnOrOff As Boolean)
 
    Log("flash status = " & flashOnOrOff)
 
End Sub

Sub b2_Click
 
    avc1.toggleFlash
 
End Sub

Sub b3_Click
 
    avc1.ZoomIn
 
End Sub

Sub b4_Click
 
    avc1.ZoomOut
 
End Sub


The library as it stands at present:

AndroidVideoCapture
Author:
Original project by: Andr.oid Eric, Adapted, modified, and wrapped by: Johan Schoeman
Version: 1
  • AndroidVideoCapture
    Events:
    • flash_toggled (flashOnOrOff as Boolean As )
    Fields:
    • QUALITY_1080P As Int
    • QUALITY_2160P As Int
    • QUALITY_480P As Int
    • QUALITY_720P As Int
    • QUALITY_CIF As Int
    • QUALITY_HIGH As Int
    • QUALITY_HIGH_SPEED_1080P As Int
    • QUALITY_HIGH_SPEED_2160P As Int
    • QUALITY_HIGH_SPEED_480P As Int
    • QUALITY_HIGH_SPEED_720P As Int
    • QUALITY_HIGH_SPEED_HIGH As Int
    • QUALITY_HIGH_SPEED_LOW As Int
    • QUALITY_LOW As Int
    • QUALITY_QCIF As Int
    • QUALITY_QVGA As Int
    • ba As BA
    Methods:
    • BringToFront
    • DesignerCreateView (base As PanelWrapper, lw As LabelWrapper, props As Map)
    • Initialize (EventName As String)
    • Invalidate
    • Invalidate2 (arg0 As Rect)
    • Invalidate3 (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
    • IsInitialized As Boolean
    • RemoveView
    • RequestFocus As Boolean
    • SendToBack
    • SetBackgroundImage (arg0 As Bitmap)
    • SetColorAnimated (arg0 As Int, arg1 As Int, arg2 As Int)
    • SetLayout (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
    • SetLayoutAnimated (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int, arg4 As Int)
    • SetVisibleAnimated (arg0 As Int, arg1 As Boolean)
    • ZoomIn
    • ZoomOut
    • releaseResources
    • setStartStopRecording
    • toggleFlash
    Properties:
    • Background As Drawable
    • Color As Int [write only]
    • Enabled As Boolean
    • Height As Int
    • Left As Int
    • MaximimDuration As Int [write only]
    • MaximumFileSize As Long [write only]
    • Tag As Object
    • Top As Int
    • VideoName As String [write only]
    • VideoQuality As Int [write only]
    • Visible As Boolean
    • Width As Int
 

Attachments

  • AndroidVideoCaptureLibFiles.zip
    7.6 KB · Views: 570
  • b4aAndroidVideoCapture.zip
    9.2 KB · Views: 576
Last edited:

mvpmedia

Member
Licensed User
Longtime User
and is there anyway to disable or modify the system tones when setstartstoprecord is triggered??
 

mvpmedia

Member
Licensed User
Longtime User
Here are minor feature requests for the lib. I don't mind donating more and more: :D

1. You updated the lib to include setorientation(90) but setOrientationHint was still set for 0. This made the videos play back sideways. Can you allow both setorientation and orientationhint to be selected upon Initialize such as (0,0) or (90,90)? If not I would like setOrientationHint(90).

2. Is there anyway to disable or modify the system tones when setstartstoprecord is triggered??

3. Live Video Preview before recording starts.
 

ovasquez

Member
Licensed User
Longtime User
CaptureVideoRecord may be configured as unspecified SupportedOrientations? when I setup this way and change the orientation of the mobile, this generate error java.lang.nullpointer.

sorry for my English
 

Johan Schoeman

Expert
Licensed User
Longtime User
CaptureVideoRecord may be configured as unspecified SupportedOrientations? when I setup this way and change the orientation of the mobile, this generate error java.lang.nullpointer.

sorry for my English
See point (1) in post #1 of this thread - it is meant for use in landscape
 

JS Hart

Member
Licensed User
Longtime User
Is there a way to set the Video recording folder (avc1.VideoFolderName) to a folder that is on a removable SD Card? It seems that it will only allow recording to the internal storage as of now...
 

hears

Active Member
Licensed User
can you share this libary JAVA code ? i try make a same libary now .
 

Johan Schoeman

Expert
Licensed User
Longtime User
can you share this libary JAVA code ? i try make a same libary now .
The Java code is in post #75 of this thread. Something that you can start with
 

biometrics

Active Member
Licensed User
Longtime User
Is it possible to set the video bit and frame rate?

If not through the library maybe with Reflection/JavaObject/inline-Java to mediaRecorder?

In the comments section of the link in post #1 for example:

mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setMaxDuration(60000);
mediaRecorder.setVideoSize(720,480);
mediaRecorder.setVideoFrameRate(24);

Btw @Johan Schoeman, I'm in Cape Town ;)
 

Johan Schoeman

Expert
Licensed User
Longtime User
Is it possible to set the video bit and frame rate?

If not through the library maybe with Reflection/JavaObject/inline-Java to mediaRecorder?

In the comments section of the link in post #1 for example:

mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setMaxDuration(60000);
mediaRecorder.setVideoSize(720,480);
mediaRecorder.setVideoFrameRate(24);

Btw @Johan Schoeman, I'm in Cape Town ;)
I will revisit this lib as soon as what I have some time available to do so (mostly on weekends). Have not looked at the code of is library in the last (at least) two years.
 

biometrics

Active Member
Licensed User
Longtime User
I will revisit this lib as soon as what I have some time available to do so (mostly on weekends). Have not looked at the code of is library in the last (at least) two years.
Thanks.

Btw I found a minor bug. Even with StopCameraOnMaxSizeDuration = False video recording stops after three seconds. I worked around that by setting MaximimDuration to 24 hours.

One more thing, it beeps when recording starts and stops. Could you make it optional.
 

biometrics

Active Member
Licensed User
Longtime User
Running your sample crashes on the line Activity.LoadLayout("main") on Android 4.0.3 with the following log:

B4X:
Error occurred on line: 38 (Main)
java.lang.RuntimeException: java.lang.NullPointerException
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:170)
   at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:209)
   at JHS.AndroidVideoCapture.main._activity_create(main.java:395)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:735)
   at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:360)
   at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:260)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
   at JHS.AndroidVideoCapture.main.afterFirstLayout(main.java:104)
   at JHS.AndroidVideoCapture.main.access$000(main.java:17)
   at JHS.AndroidVideoCapture.main$WaitForLayout.run(main.java:82)
   at android.os.Handler.handleCallback(Handler.java:605)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4424)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
   at android.view.ViewGroup.addViewInner(ViewGroup.java:3336)
   at android.view.ViewGroup.addView(ViewGroup.java:3208)
   at android.view.ViewGroup.addView(ViewGroup.java:3188)
   at videowrapper.videoWrapper.AddToParent(videoWrapper.java:201)
   at videowrapper.videoWrapper.DesignerCreateView(videoWrapper.java:209)
   at anywheresoftware.b4a.objects.CustomViewWrapper.AfterDesignerScript(CustomViewWrapper.java:70)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:162)
   ... 22 more
** Activity (main) Resume **
 

Rusty

Well-Known Member
Licensed User
Longtime User
Using your latest sample, I get: Any ideas/suggestions?
Sub b1_Click
Log("SELECTED INDEX = " & ns2.SelectedIndex)
' Log(r3.Get(ns2.SelectedIndex))
' Log(r4.Get(ns2.SelectedIndex))
avc1.setStartStopRecording
End Sub
...
Error occurred on line: 133 (Main)
java.lang.RuntimeException: stop failed.
at android.media.MediaRecorder.stop(Native Method)
at videowrapper.videoWrapper.setStartStopRecording(videoWrapper.java:267)
at JHS.AndroidVideoCapture.main._b1_click(main.java:653)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:738)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:357)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:260)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
at android.view.View.performClick(View.java:4565)
at android.view.View$PerformClick.run(View.java:18641)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5021)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:827)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:643)
at dalvik.system.NativeStart.main(Native Method)
 
Top