首页 > 解决方案 > 如何在来自 HLS 流媒体的 exoplayer(android 应用程序)中播放加密视频?

问题描述

我现在正在使用 FFMPEG 使用 HLS 流式传输 mp4 文件。我正在使用此链接启用加密: https ://hlsbook.net/how-to-encrypt-hls-video-with-ffmpeg/

要在我的 android 应用程序中播放视频,我使用 exoplayer,下面是我播放视频的源代码:

Player player;
private MediaSource buildMediaSource(Uri uri) {
     TrackSelection.Factory adaptiveTrackSelection = new AdaptiveTrackSelection.Factory(new DefaultBandwidthMeter());
    player = ExoPlayerFactory.newSimpleInstance(
            this,
            new DefaultTrackSelector(adaptiveTrackSelection));
    playerView.setPlayer(player);
    // These factories are used to construct two media sources.
    DefaultBandwidthMeter defaultBandwidthMeter = DefaultBandwidthMeter.getSingletonInstance(this);
    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(mContext,
            Util.getUserAgent(mContext, "cookvid"), defaultBandwidthMeter);
    //DataSource.Factory dataSourceFactory =
    //        new DefaultDataSourceFactory(this, "exoplayer-codelab");

    HlsMediaSource.Factory mediaSourceFactory = new HlsMediaSource.Factory(dataSourceFactory);
    return mediaSourceFactory.createMediaSource(uri);
    //return new ProgressiveMediaSource.Factory(dataSourceFactory)
     //       .createMediaSource(uri);
}
private void initializePlayer() {
    Uri uri = Uri.parse(getString(R.string.media_url_hls));
    MediaSource mediaSource = buildMediaSource(uri);
    player.setPlayWhenReady(playWhenReady);
    player.seekTo(currentWindow, playbackPosition);
    player.addListener(playbackStateListener);
    player.prepare(mediaSource, false, false);
}

但是使用此代码,我无法在应用程序中播放视频,如果我不使用此加密,那么 exoplayer 可以毫无问题地播放视频。

请帮助我,我是 exoplayer 方面的新手。

标签: androidencryptionffmpeghttp-live-streamingexoplayer

解决方案


我在 Kotlin 中为您创建了一个示例以使其工作:

class MainActivity : AppCompatActivity() {

    private var exoPlayer: SimpleExoPlayer? = null
    private var trackSelector: DefaultTrackSelector? = null
    var drmSessionManager: DefaultDrmSessionManager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        trackSelector = DefaultTrackSelector(this)
        exoPlayer = SimpleExoPlayer.Builder(this)
            .setTrackSelector(trackSelector!!)
            .build()

        player_view.player = exoPlayer
        
       var uri =  Uri.fromFile( File("//android_asset/legend_enc.mp4"))
       playVideo(uri, "zX65/4jzTK6wYYWwACTkwg", "Y8tfcYTdS2iaXF/xHuajKA")

    }

    private fun playVideo(url: Uri, id: String, value: String){
        try {
            drmSessionManager =
                Util.getDrmUuid(C.CLEARKEY_UUID.toString())?.let { buildDrmSessionManager(
                    it,
                    true,
                    id,
                    value
                ) }
        } catch (e: UnsupportedDrmException) {
            e.printStackTrace()
        }
        exoPlayer?.setMediaSource(buildDashMediaSource(url))
        exoPlayer?.prepare()
        exoPlayer?.playWhenReady = true
    }

    private fun buildDashMediaSource(uri: Uri): MediaSource {
        val dashChunkSourceFactory = DefaultDataSourceFactory(this, "agent")
        return ProgressiveMediaSource.Factory(dashChunkSourceFactory)
            .setDrmSessionManager(drmSessionManager ?: DrmSessionManager.DUMMY)
            .createMediaSource(uri)
    }

    @Throws(UnsupportedDrmException::class)
    private fun buildDrmSessionManager(uuid: UUID, multiSession: Boolean, id: String, value: String): DefaultDrmSessionManager {
        val drmCallback = LocalMediaDrmCallback("{\"keys\":[{\"kty\":\"oct\",\"k\":\"${value}\",\"kid\":\"${id}\"}],\"type\":\"temporary\"}".toByteArray())
        val mediaDrm = FrameworkMediaDrm.newInstance(uuid)
        return DefaultDrmSessionManager(uuid, mediaDrm, drmCallback, null, multiSession)
    }
}

推荐阅读