如何在Android Studio中用Kotlin下载YouTube音频?
在Android Studio中用Kotlin实现YouTube音频下载的可行方案
首先明确:YouTube官方条款禁止未经授权下载平台内容,以下方案仅作技术学习参考,使用时需严格遵守平台规则及当地版权法律。
核心实现思路
通过第三方解析库获取YouTube视频的音频流地址,再通过网络请求将音频文件保存到本地存储。
具体步骤
1. 添加依赖与权限
在模块级build.gradle的dependencies块中添加解析库:
implementation "com.github.HaarigerHarald:android-youtubeExtractor:2.1.0"
在AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.INTERNET" /> <!-- Android 9及以下需添加存储权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" /> <!-- Android 10+ 需添加媒体访问权限 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
2. 解析音频下载链接
编写Kotlin代码解析YouTube视频的音频流地址:
import com.github.haroldadmin.youtubeExtractor.VideoMeta import com.github.haroldadmin.youtubeExtractor.YouTubeExtractor import com.github.haroldadmin.youtubeExtractor.YtFile fun getAudioDownloadUrl(videoUrl: String, callback: (String?, String?) -> Unit) { object : YouTubeExtractor() { override fun onExtractionComplete(ytFiles: Map<Int, YtFile>?, videoMeta: VideoMeta?) { ytFiles?.values?.firstOrNull { it.format.isAudioOnly }?.let { audioFile -> val title = videoMeta?.title ?: "unknown_audio" callback(audioFile.url, title) } ?: callback(null, null) } }.extract(videoUrl, true, true) }
3. 下载并保存音频文件
实现音频下载逻辑,适配不同Android版本的存储规则:
import android.content.Context import android.os.Environment import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File import java.io.FileOutputStream import java.net.URL fun downloadAudioToLocal(context: Context, audioUrl: String, fileName: String) { GlobalScope.launch(Dispatchers.IO) { try { val url = URL(audioUrl) val connection = url.openConnection() connection.connect() // 确定存储目录(适配Scoped Storage) val saveDir = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { context.getExternalFilesDir(Environment.DIRECTORY_MUSIC) } else { Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) } saveDir?.let { dir -> if (!dir.exists()) dir.mkdirs() val audioFile = File(dir, "$fileName.m4a") val inputStream = connection.inputStream val outputStream = FileOutputStream(audioFile) val buffer = ByteArray(4096) var bytesRead: Int while (inputStream.read(buffer).also { bytesRead = it } != -1) { outputStream.write(buffer, 0, bytesRead) } outputStream.close() inputStream.close() // 主线程更新UI(比如提示下载完成) withContext(Dispatchers.Main) { // TODO: 实现下载完成后的UI逻辑 } } } catch (e: Exception) { e.printStackTrace() withContext(Dispatchers.Main) { // TODO: 处理下载失败的UI逻辑 } } } }
4. 调用示例
在Activity或ViewModel中组合调用上述方法:
// 替换为目标YouTube视频链接 val targetVideoUrl = "https://www.youtube.com/watch?v=xxxxxxx" getAudioDownloadUrl(targetVideoUrl) { audioUrl, title -> if (audioUrl != null && title != null) { downloadAudioToLocal(this, audioUrl, title) } else { // 处理解析失败的情况 } }
关键注意事项
- 第三方解析库可能因YouTube接口更新失效,需定期关注库的维护状态
- 不得将该功能用于侵犯他人版权的场景,需确保下载内容的使用合规
- Android 10+ 需适配Scoped Storage规则,避免存储权限问题
内容的提问来源于stack exchange,提问作者Valentine
相关产品推荐
相关产品推荐

