β οΈ Some major changes have been made in version 1.0.20 for improving performance in helper library. Before updating, please review the usage guide again; otherwise, you may encounter import issues.
Hats off to JunkFood for his outstanding work on youtubedl-android! π
His contribution to the Android community has made video downloading easier, and we deeply appreciate his efforts.
πΉ Our library, YoutubeDL-Boom, is still built on his foundation.
πΉ If you find this project useful and want to support the original work, please donate to him, not us. π
π Visit JunkFood's Repository and show some love! β€οΈ
While youtubedl-android is an excellent library (huge thanks to JunkFood for their work β€οΈ), we found some areas that could be improved to make it more efficient and lightweight. Hereβs what led us to create youtubedl-boom:
- Issue: If a download is started using the FFmpeg downloader and the process is canceled, FFmpeg keeps running in the background and continues downloading, causing unnecessary resource consumption.
- Solution: We properly kill the child process of FFmpeg when a download is canceled, ensuring no unwanted downloads occur.
- Issue: When using FFmpeg for downloading, there was no callback string/result to track progress or completion.
- Solution: We now capture and return output from the FFmpeg process, giving proper feedback on download status.
- Issue: The previous implementation relied on threads, which are resource-heavy and can lead to performance issues.
- Solution: We replaced threads with coroutines, making the code more efficient and responsive.
- Issue: youtubedl-android used multiple modules for simple tasks, making it harder to manage.
- Solution: We simplified the structure by consolidating it into a single module with a single dependency, making integration much easier.
- Issue: Writing reflection methods can be tedious when distributing the module via DFM.
- Solution: We provide a seamless API to communicate with
youtubedl-boom
effortlessly.
With these improvements, youtubedl-boom is now more efficient, lightweight, and developer-friendly π.
without DFM. use below in app'level gradle file:
To use youtubedl-boom
in your Android project, add the following two dependencies in your build.gradle.kts
:
dependencies {
implementation("io.github.farimarwat:youtubedl-boom:1.0.20")
implementation("io.github.farimarwat:youtubedl-boom-commons:1.2")
}
Incase of DFM, include the above βοΈ in DFM level and below in app's level: Details are below in the #2 section
dependencies {
implementation("io.github.farimarwat:youtubedl-boom-helper:1.6")
implementation("io.github.farimarwat:youtubedl-boom-commons:1.2")
}
-keep class com.farimarwat.** { *; }
-keep class org.apache.commons.compress.archivers.zip.** { *; }
Include this in app's manifest
<application
android:extractNativeLibs="true"
...
>
...
</application>
Note: If you are packaging the youtubedl-boom
with the app then there is no need to use Helper API
but direct packaging will increase the apk size
We create a nullable global variable to store the YoutubeDL
instance.
This will be initialized after a successful YouTubeDL setup.
var youtubeDl: YoutubeDL? = null
- This is usually done in the App class or an appropriate singleton.
- Initially
null
, it will be set when initialization succeeds.
YoutubeDL.init(
appContext = this,
withFfmpeg = true, //Default is false
withAria2c = false, //Default is false
onSuccess = {
youtubeDl = it
},
onError = {
Timber.e(it)
}
)
βΌοΈ I recommend enabling FFMPEG, as it is required for some videos that are split. It is essential for merging audio and video after a successful download.
youtubeDl?.getInfo(
url = "https://www.youtube.com/watch?v=example",
onSuccess = { videoInfo ->
println("Title: ${videoInfo.title}")
println("Duration: ${videoInfo.duration}")
},
onError = { error ->
println("Error: ${error.message}")
}
)
url
β The YouTube video link.onSuccess
β Callback function that receivesVideoInfo
if retrieval succeeds.- Prints the title and duration of the video.
onError
β Callback function that handles errors if fetching fails.- Prints the error message.
- The video extraction process runs in the background (IO thread) using Coroutines, ensuring the main UI thread remains free.
- The function spawns a separate process to execute yt-dlp with the
--dump-json
option to fetch video details. - Standard output (
stdout
) is captured and parsed into a structuredVideoInfo
object. - The
onSuccess
oronError
callback is triggered based on the result.
This ensures smooth, non-blocking execution while retrieving video metadata.
The download
function allows you to download videos using yt-dlp
. It runs asynchronously in the background and provides callbacks to track progress, handle errors, and retrieve the final response.
val request = YoutubeDLRequest("https://www.youtube.com/watch?v=example")
// Specify output directory and filename format
request.addOption("-o", StoragePermissionHelper.downloadDir.getAbsolutePath() + "/%(title)s.%(ext)s")
// Use ffmpeg as the downloader (optional) mostly used for live streams
request.addOption("--downloader", "ffmpeg")
val job = download(
request = request,
pId = "custom-process-id", // Optional. If not provided, an ID is auto-generated.
progressCallBack = { percentage, elapsedTime, outputLine ->
println("Progress: $percentage% | Time: $elapsedTime ms | yt-dlp output: $outputLine")
// The `outputLine` contains raw yt-dlp output. Parse it if needed.
},
onStartProcess = { processId ->
println("Download started with Process ID: $processId")
},
onEndProcess = { response ->
println("Download completed in ${response.elapsedTime} ms")
println("Output: ${response.out}")
},
onError = { error ->
println("Download failed: ${error.message}")
}
)
-
request
: AYoutubeDLRequest
object that specifies the video URL and additional download options.- The
-o
option sets the output file location and naming format. - The
--downloader ffmpeg
option ensuresffmpeg
is used for handling video conversions.
- The
-
pId
(optional): A unique Process ID to track the download. If omitted, an ID is auto-generated and returned viaonStartProcess
. -
progressCallBack
:percentage
: The download progress in percentage.elapsedTime
: The time elapsed since the download started (in milliseconds).outputLine
: The raw output string fromyt-dlp
, which can contain useful details such as speed, estimated time remaining, or other metadata.
-
onStartProcess
: Invoked when the download process starts, providing the assigned Process ID. -
onEndProcess
: Called when the download completes, returning aYoutubeDLResponse
that includes:response.elapsedTime
: The total time taken for the download.response.out
: The standard output generated byyt-dlp
.
-
onError
: Triggered if an error occurs during the download, returning the error message.
- The download process executes asynchronously in the background using Kotlin Coroutines (
Dispatchers.IO
). yt-dlp
generates detailed logs inoutputLine
, which can be parsed for specific information.- The function ensures proper error handling and prevents duplicate Process IDs.
Note:Every call is same like above but add R
before YoutubeDL
object
Declare a global flag isInitialized
(may be in app class) and set it after successful initialization.
RYoutubeDL.init(
appContext = this,
withFfmpeg = true, // Default is false
withAria2c = false, // Default is false
onSuccess = {
isInitialized = true
},
onError = {
Timber.e(it)
}
)
Use the parameter withFfmpeg
only if you want to download files with FFMPEG
, and the same applies to Aria2c
.
RYoutubeDL.getInfo(
url = url,
onSuccess = { videoInfo ->
Timber.i(videoInfo.title)
},
onError = { Timber.i(it) }
)
url
: A string URL for supported downloads.onSuccess
: Returns aVideoInfo
object
Note: Never forget to check isInitialized
to avoid unexpected behavior.
First, create a download request:
val request = YoutubeDLRequest(url)
Next, add options:
request.addOption(
"-o",
"${StoragePermissionHelper.downloadDir.absolutePath}/%(title)s.%(ext)s"
)
request.addOption("--no-part")
Finally, call the download
function:
RYoutubeDL.download(
request = request,
progressCallBack = { progress, eta, line ->
// Handle progress updates
},
onStartProcess = { id ->
// Handle process start
},
onEndProcess = { response ->
// Handle process completion
},
onError = { error ->
// Handle errors
}
)
RYoutubeDL.destroyProcessById(processId)
RYoutubeDL.updateYoutubeDL(
appContext = this,
updateChannel = UpdateChannel.MASTER,
onSuccess = { status ->
},
onError = {
Timber.i(it)
}
)
val version = RYoutubeDL.version(this)
val versionName = RYoutubeDL.versionName(this)
youtubedl-boom:1.0.20
- Moved YoutubeDlRequest, YoutubeDlOption, YoutubeDlResponse, VideoInfo, VideoFormat to commons library
- The above changes made because these are common between youtubedl-helper and youtubedl-boom
1.0.18
- Removed dynamic download for library files.
- Now packaged with the library
- Fixed issue #7
- 1.0.17
Fix ffmpeg initialization on initial setup
-
1.0.16
Fix InterruptedIOException crash
-
1.0.15
Fix OutOfMemoryError
-
1.0.14:
Foreground service support added to download files
-
1.0.6:
Fixed: failed to initialize #4
I am a Senior Mobile Developer specializing in Android and iOS, with 7+ years of experience in Android development. Additionally, I have 2+ years of experience as a Full-Stack Web Developer, working with PHP, Django, and Golang.
π LinkedIn: Farman Ullah Marwat