当前位置: 首页 > 知识库问答 >
问题:

Android Exoplayer-不同视频质量的URL和手动更改

陆绍辉
2023-03-14
{
     "lowQualityUrl":"string url",
     "mediumQualityUrl":"string url",
     "highQualityUrl":"string url"
}

共有1个答案

孟永望
2023-03-14

我找到了一个解决办法,或者更确切地说是一个解决这个问题的变通办法。我在RecylCerView中使用exoplayer。这段代码可能需要一些优化。

我从这个问题下面的另一个答案中得到了这个想法,这个答案有这个github链接,但我认为作者删除了它。我所做的是创建一个类来保存特定视频的所有URL。然后在exoplayer上面显示一个旋转器,当用户选择一个特定的质量时,我用新的URL准备exoplayer,然后搜索到以前播放的位置。您可以忽略StringUtils方法。

VideoPlayerConfig.kt

object VideoPlayerConfig {
//Minimum Video you want to buffer while Playing
val MIN_BUFFER_DURATION = 3000
//Max Video you want to buffer during PlayBack
val MAX_BUFFER_DURATION = 5000
//Min Video you want to buffer before start Playing it
val MIN_PLAYBACK_START_BUFFER = 1500
//Min video You want to buffer when user resumes video
val MIN_PLAYBACK_RESUME_BUFFER = 5000
} 
class VideoQuality {
private val videoQualityUrls = HashMap<String, String>()

companion object {
    val LOW = getStringResource(R.string.low)
    val MEDIUM = getStringResource(R.string.medium)
    val HIGH = getStringResource(R.string.high)
}

val qualityArray
    get() = arrayListOf<String>().apply {
        if (hasQuality(LOW)) add(LOW)
        if (hasQuality(MEDIUM)) add(MEDIUM)
        if (hasQuality(HIGH)) add(HIGH)
    }
var defaultVideoQuality: String? = HIGH

var lowQuality: String?
    set(value) {
        setVideoQualityUrl(LOW, value)
    }
    get() = videoQualityUrls[LOW] ?: ""
var mediumQuality: String?
    set(value) {
        setVideoQualityUrl(MEDIUM, value)
    }
    get() = videoQualityUrls[MEDIUM] ?: ""
var highQuality: String?
    set(value) {
        setVideoQualityUrl(HIGH, value)
    }
    get() = videoQualityUrls[HIGH] ?: ""

private fun setVideoQualityUrl(quality: String?, url: String?) {
    if (url != null && quality != null) {
        videoQualityUrls[quality] = url
    }
}

private fun hasQuality(quality: String?): Boolean {
    if (videoQualityUrls[quality] == null) {
        return false
    }
    return true
}

fun getVideoQualityUrl(quality: String?): String? {
    return videoQualityUrls[quality]
}
}
private fun initializePlayer() {
    if (exoPlayer == null) {

        val loadControl = DefaultLoadControl.Builder()
            .setBufferDurationsMs(2 * VideoPlayerConfig.MIN_BUFFER_DURATION, 2 * VideoPlayerConfig.MAX_BUFFER_DURATION, VideoPlayerConfig.MIN_PLAYBACK_START_BUFFER, VideoPlayerConfig.MIN_PLAYBACK_RESUME_BUFFER)
            .createDefaultLoadControl()
        //Create a default TrackSelector
        val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory()
        val trackSelector = DefaultTrackSelector(videoTrackSelectionFactory)
        exoPlayer = ExoPlayerFactory.newSimpleInstance(itemView.context, DefaultRenderersFactory(itemView.context), trackSelector, loadControl)
        exoPlayer!!.addListener(PlayEventListener())
        val videoQualityInfo:VideoQuality = videoListVideoDataHolderData!!.videoQualityUrls //Just an object that i created and stored in a dataHolder for this view.
        val url = videoQualityInfo.getVideoQualityUrl(videoQualityInfo.defaultVideoQuality) ?: ""
        preparePlayer(url)
    }
}

private fun preparePlayer(url: String) {

    if (url.isNotEmpty()) {
        val mediaSource = buildMediaSource(StringUtils.makeHttpUrl(url))
        exoPlayer?.prepare(mediaSource)
        videoView.player = exoPlayer
    } else {
        Log.d(APPTAG, "NO DEFAULT URL")
    }
}
private fun buildMediaSource(url: String): ProgressiveMediaSource {
    val mUri: Uri = Uri.parse(url)
    val dataSourceFactory = DefaultDataSourceFactory(
        itemView.context,
        Util.getUserAgent(itemView.context, getStringResource(R.string.app_name))
    )
    val videoSource = ProgressiveMediaSource.Factory(dataSourceFactory)
        .createMediaSource(mUri)
    return videoSource
}
videoQualitySpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
        override fun onNothingSelected(parent: AdapterView<*>?) {

        }

        override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            val currentTime = exoPlayer?.currentPosition
            val isReadyToPlay = exoPlayer?.playWhenReady
            val urlToBuild = when (videoQualityUrls.qualityArray[position]) {
                VideoQuality.LOW -> videoQualityUrls.lowQuality
                VideoQuality.MEDIUM -> videoQualityUrls.mediumQuality
                else -> videoQualityUrls.highQuality
            }
            Log.d(APPTAG, "VIDEO DETAILS :::: ${currentTime} ${isReadyToPlay} ${urlToBuild}")
            if (!urlToBuild.isNullOrEmpty()) {
                val mediaSource = buildMediaSource(StringUtils.makeHttpUrl(urlToBuild))
                exoPlayer?.prepare(mediaSource)
                exoPlayer?.playWhenReady = isReadyToPlay ?: false
                exoPlayer?.seekTo(currentTime ?: 0)
            }

        }
    }
 类似资料:
  • 我想问我应该使用什么命令从mpd清单中选择视频质量? MPD清单链接 这里是mpd文件: 视频没有用DRM加密。当我尝试用FFmpeg下载时,成功了,但是FFmpeg自动选择了质量最差的(144p)。 我使用的FFmpeg命令: 来自ffmpeg的结果 试过youtube dl 注意:只需将(点)更改为

  • 我正在创建IPTV应用程序。在这种情况下,Exoplayer用于视频流,现在的要求是在运行时改变视频质量(自动,720p,1080p,高清),就像YouTube一样。 我已经找到了2-3个解决方案,但我不明白如何实现这一点。

  • crf 20是相当高的质量,接近100%,恢复的帧应该接近原始。视频播放器暂停帧显示足够的质量。(虽然我不能说它是否在关键帧上) ffmpeg版本信息:

  • 使用ffmpeg concat连接多个文件似乎会导致音频的时间戳或偏移不匹配。我试过几个视频,发现H.264/MP4也有同样的问题。 使用并对视频进行编码似乎可以很好地工作。当ffmpeg执行全部转换计算时,音频保持同步,似乎可以得到所有正确的结果。 然而,简单地将视频级联而不进行任何转换或编码会导致同步问题缓慢增加。显然,对视频进行编码而不是简单地加入它们将导致信息/质量的损失,所以我宁愿找到一

  • 有个透明视频 text.mov 和一个背景图 bg.jpg(将作为视频背景),合并之后视频的质量明显降低,设置了帧率、码流、编码方式都不行,有没有解决过类似问题的,悬赏千元求解,谢谢诸位!!!

  • Java怎么提升视频质量,比如我有个视频,但清晰度很低。想用JavaCV或者其它库,怎么提升视频清晰度,降噪等等,谢谢。 用JavaCV试了,效果但效果不太好。 代码如下: