B4A Class MobileFFmpeg

This is a small class that shows how to call from B4A the FFMPEG wrapper created by Taner Sener: https://github.com/tanersener/mobile-ffmpeg. It seems to work with the latest SDK which apparently causes a problem with this FFMPEG library: https://www.b4x.com/android/forum/t...b4x-with-inline-java-only.108905/#post-789281. The class uses the JavaObject library.

Taner has provided packages with different FFMPEG capabilities (and file sizes) so you can use the one that best meets your requirements. I have only used and tested the min package (https://github.com/tanersener/mobile-ffmpeg/releases/download/v4.4/mobile-ffmpeg-min-4.4.aar). Copy the required aar file to the Additional Libraries folder and make sure you use a "#AdditionalJar" line that reflects the name of the package you are using.

My class has only exposed some of Taner's wrapper but it should be straightforward to add anything that I have not covered. The following is an example of using the class. It adds an audio track (audio.mp3) to a video (video.mp4). Check the logs for the output. I have also attached the project which includes this code. You will need to add video.mp4 and music.mp3 to the project for it to work.

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

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

#AdditionalJar: mobile-ffmpeg-min-4.4.LTS.aar

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

Sub Globals
    'These global variables will be redeclared each time the activity is created.
End Sub

Sub Activity_Create(FirstTime As Boolean)
    aMobileFFMPEG.Initialize(Me, "FFMPEG")
    Dim levels() As Object=aMobileFFMPEG.GetLogLevels
    Log("Logging levels:")
    For Each aLevel As Object In levels
        Log(aLevel)
    Next
    Log("Using log level: AV_LOG_WARNING")
    'if you want to see some log output, set to AV_LOG_INFO or higher
    aMobileFFMPEG.setLogLevelByConstant("AV_LOG_WARNING")
    aMobileFFMPEG.enableLogCallback
    aMobileFFMPEG.enableStatisticsCallback
    Dim abiName As String=aMobileFFMPEG.GetAbi 'ignore
    Log("ABI: " & abiName)
    File.Copy(File.DirAssets, "video.mp4", File.DirInternal, "video.mp4")
    File.Copy(File.DirAssets, "music.mp3", File.DirInternal, "music.mp3")
    'adds an audio track to a video
    Dim theCmd As String="-y -i " & File.Combine(File.DirInternal, "video.mp4") & " -i " & File.Combine(File.DirInternal, "music.mp3") & " -c copy " & File.Combine(File.DirInternal, "videomusic.mp4")
    Dim id As Long=aMobileFFMPEG.ExecuteAsync(Regex.Split(" ",theCmd))
    Log("Running with Execution Id: " & id)
End Sub

Sub FFMPEG_Event(id As Long, retCode As Int)
    Log("Callback with Execution Id: " & id & " and return code: " & retCode)
    If File.Exists(File.DirInternal, "videomusic.mp4") Then
        Log("videomusic.mp4 file size: " & File.Size(File.DirInternal, "videomusic.mp4"))
    End If
    MsgboxAsync("Check the logs", "Mobile-FFMPEG test")
End Sub

Sub FFMPEG_Log(msg As String)
    Log("log: " & msg)
End Sub

Sub FFMPEG_Statistics(msg As String)
    Log("Statistics: " & msg)
End Sub
 

Attachments

  • mobileFFmpeg.bas
    3.1 KB · Views: 352
  • FFMPEG_Test.zip
    9.5 KB · Views: 379

CaptKronos

Active Member
Licensed User
If you mean convert a video from one file format to another format or to a video file with a higher compression, then yes you can. Anything you can do with FFMPEG, you can do with this class.
 

hl88

Member
I copy my own video.mp4 and audio.mp3 to project's folder. the ffmpeg command "ffmpeg -i video.mp4 -i audio.wav -c copy videomusic.mp4" doesn't work. I find the ffmpeg command to replace my video.mp4's audio stream and It works šŸ˜‚
B4X:
Dim rp As RuntimePermission
shared = rp.GetSafeDirDefaultExternal("")
...
Dim theCmd As String="-y -i " & File.Combine(File.DirInternal, "video.mp4") & " -i " & File.Combine(File.DirInternal, "music.mp3") & " -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 " & File.Combine(shared, "videomusic.mp4")

by the way, can someone help me how to save output video to other location like [phone Internal storage]:\Converted\ or some proper folder picker library
 

CaptKronos

Active Member
Licensed User
I'm no FFMPEG expert but I would guess that the problem you had may have been because your video already had an audio track.
Also, and not related to your problem, how I used Regex.Split(" ",theCmd) to create the array of parameters was a bit lazy/dangerous since in the general case theCmd may contain " " characters that aren't just between FFMPEG parameters, such as folder names with spaces.
 

Nkalampika

Active Member
Licensed User
the aar file has big size, i just want to use to compress videos, how to reduce size of aar file to use only compress functions
 

CaptKronos

Active Member
Licensed User
If you are happy sacrificing compatibility with certain architectures, you could open up the aar file and remove the unwanted architectures. The x86 ones are probably the safest to remove. Obviously it depends on your requirements.
 

moster67

Expert
Licensed User
Longtime User
Yep, @CaptKronos is correct.
Or if you publish on Google Play Store, the new App Bundle should take care of that, and no need to worry...
 
Last edited:

hl88

Member
I'm no FFMPEG expert but I would guess that the problem you had may have been because your video already had an audio track.
Also, and not related to your problem, how I used Regex.Split(" ",theCmd) to create the array of parameters was a bit lazy/dangerous since in the general case theCmd may contain " " characters that aren't just between FFMPEG parameters, such as folder names with spaces.
in my experience ffmpeg already got problem with files/folder names with spaces on PC
I found my answer to get permission to save output video to DirRootInternal, now I tried some commands involve drawtext and get errors

B4X:
Dim theCmd As String="-y -i " & FileInput & $" -vf "drawtext=text='watermark':x=(1100-text_w):y=(600-text_h):fontsize=32:fontcolor=black:box=1:[email protected]:boxborderw=5" -c:a copy "$ & DirOutput & "/videomusic.mp4"

Error code
log: [AVFilterGraph @ 0x7344416280] No such filter: '"drawtext'
log: Error reinitializing filters!
log: Failed to inject frame into filter network: Invalid argument
log: Error while processing the decoded data for stream #0:0

Remove -y from the begin of the string
log: [NULL @ 0x73af489a00] Unable to find a suitable output format for ''
 

hl88

Member
Finally, I found the culprit and solved the case šŸ˜‚
  • drawtext filter is not available on min package
  • remove double quote
  • add "-y" to the beginning. No idea what -y is for, but most of my commands on pc doesn't need -y
  • Tips #4 , ffmpeg requires default font path to render text. Hoping you include Config.setFontDirectory in next update

Here is my fully working command
B4X:
Dim theCmd As String="-y -i " & FileInput & $" -vf drawtext=fontfile='"$ & File.Combine(File.DirInternal, "font.ttf") & $":text='watermark':x=(1100-text_w):y=(600-text_h):fontsize=32:fontcolor=black:box=1:[email protected]:boxborderw=5 -c:a copy "$ & DirOutput & "/videomusic.mp4"
 
Top