MP3-Downloader

Kotlin Android

Youtube to MP3 Coverter app

? Previews

Download apk

Demo video ?

? Tech Stacks & Open Source Libraries

  • Jetpack Compose
  • ViewModel
  • Hilt
  • Moshi
  • Chaquopy : To create an environment to run .py script
  • mobile-ffmpeg : To convert .m4a to mp3
  • yt-dlp : To download .m4a audio from youtube

⭐ Key features

  • Grabbing & Downloading : Chaquopy used to create an environment for running main.py. It contains get_video_info() to grab video info and download_audio() to download m4a audio. During download, it also returns invokes a callback to log progress on Android side.
  • Converting Ffmpeg command to convert file
ffmpeg -i $inputFile -c:v copy -c:a libmp3lame -q:a 4 $outputFile
  • Saving: Input and output streams used

? Key challenges faced

  • UI related ❓ Creating multiple screens vs single screen ❓ Architecturing the UI for different steps ? Solution: Broke down the UI into state machine. During a session, the app is always in one of the following HomeScreenStep

  • yt-dlp related ❓ How to use yt-dlp (python) in Android project ❓ Understanding yt-dlp and creating script for it ❓ How to send progress of download to Android ? Solution: Used Chaquopy and yt-dlp’s doc

  • ffmpeg related ❓ How to use ffmpeg in Android project ❓ Ffmpeg command to convert file ? Solution: Used mobile-ffmpeg and ffmpeg’s doc

⭐ Possible Improvements

  • Could have added tests
  • Could have polished the UI

File structure

Click me

MP3 Downloader
│   AndroidManifest.xml
│
├───java
│   └───com
│       └───example
│           └───mp3downloader
│               │   App.kt
│               │   MainActivity.kt
│               │
│               ├───data
│               │   └───model
│               │           DownloadProgressInfo.kt
│               │           VideoInfo.kt
│               │
│               ├───di
│               │       AppModule.kt
│               │
│               ├───presentation
│               │   ├───common
│               │   │   │   DestinationFolderItem.kt
│               │   │   │   DownloadButton.kt
│               │   │   │   ScreenHeader.kt
│               │   │   │   TextFieldItem.kt
│               │   │   │   VideoInfoItem.kt
│               │   │   │
│               │   │   └───step_content
│               │   │           ConvertingStepContent.kt
│               │   │           DownloadingStepContent.kt
│               │   │           FailureStepContent.kt
│               │   │           SavingStepContent.kt
│               │   │           SuccessStepContent.kt
│               │   │
│               │   └───home_screen
│               │           HomeScreen.kt
│               │           HomeScreenEvents.kt
│               │           HomeScreenState.kt
│               │           HomeViewModel.kt
│               │
│               └───ui
│                   └───theme
│                           Color.kt
│                           Theme.kt
│                           Type.kt
│
├───python
│       main.py
│
└───res
  ├───drawable
  │       ic_launcher_background.xml
  │       yt_logo.png
  │
  ├───drawable-v24
  │       ic_launcher_foreground.xml
  │
  ├───font
  │       plus_jakarta_sans_bold.ttf
  │       plus_jakarta_sans_semibold.ttf
  │
  ├───mipmap-anydpi-v26
  │       ic_launcher.xml
  │       ic_launcher_round.xml
  │
  ├───mipmap-hdpi
  │       ic_launcher.webp
  │       ic_launcher_round.webp
  │
  ├───mipmap-mdpi
  │       ic_launcher.webp
  │       ic_launcher_round.webp
  │
  ├───mipmap-xhdpi
  │       ic_launcher.webp
  │       ic_launcher_round.webp
  │
  ├───mipmap-xxhdpi
  │       ic_launcher.webp
  │       ic_launcher_round.webp
  │
  ├───mipmap-xxxhdpi
  │       ic_launcher.webp
  │       ic_launcher_round.webp
  │
  ├───values
  │       colors.xml
  │       strings.xml
  │       themes.xml
  │
  └───xml
          backup_rules.xml
          data_extraction_rules.xml

GitHub

View Github