Воспроизведение зашифрованных hls в exoplayer с использованием зашифрованных ключей - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь воспроизвести зашифрованное видео, используя файл .m3u8. Я сохранил свое видео в AWS и создал файлы .ts и мастер-плейлист. Aws предоставил мне несколько ключей для этого зашифрованного видеофайла. Теперь я должен использовать эти ключи в exoplayer. Я пытался использовать Aes128DataSource и DrmSessionManager, но безуспешно.

Типы ключей:

Encryption Key: ####################################################################
Encryption Key MD5: ################
Encryption Initialization Vector : #############

Ниже код, который я использую для воспроизведения видео hls. Он воспроизводит видео без проблем. Мне просто нужно знать, где и как использовать ключи для воспроизведения зашифрованного видео.

            String VIDEO_URL = "https://s3.amazonaws.com/######.###.##/videos/mobiletest/mobilemaster.m3u8";

            //Create a default TrackSelector
            BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
            TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
            TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

            // Create a default LoadControl
            LoadControl loadControl = new DefaultLoadControl();
            //Bis. Create a RenderFactory
            RenderersFactory renderersFactory = new DefaultRenderersFactory(this);


            //Create the player
            player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
            simpleExoPlayerView = new SimpleExoPlayerView(this);
            simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);


            //Set media controller
            simpleExoPlayerView.setUseController(true);
            simpleExoPlayerView.requestFocus();

            // Bind the player to the view.
            simpleExoPlayerView.setPlayer(player);

            // Set the media source
            Uri mp4VideoUri = Uri.parse(VIDEO_URL);

            //Measures bandwidth during playback. Can be null if not required.
            DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();

            //Produces DataSource instances through which media data is loaded.
            DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "PiwikVideoApp"), bandwidthMeterA);

            //Produces Extractor instances for parsing the media data.
            ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

            //FOR LIVE STREAM LINK:
            MediaSource videoSource = new HlsMediaSource(mp4VideoUri, dataSourceFactory, 1, null, null);
            final MediaSource mediaSource = videoSource;


            player.prepare(videoSource);

Я зашифровал видео с помощью AWS Elastic Transcoder и использовал версию exoplayer: 2.6.0

1 Ответ

0 голосов
/ 18 января 2019

Я нашел решение. Трюк, который вам нужно сделать, это создать свои собственные источники данных. Вам нужно создать класс, который расширяет HttpDataSource.BaseFactory и добавить некоторый код из DefaultHttpDataSourceFactory. Я знаю, это звучит безумно, но я решил это таким образом. Не волнуйтесь, я вставляю здесь весь код этого пользовательского класса.

import android.support.annotation.Nullable;

import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;

public class CustomDataSourcesFactory extends HttpDataSource.BaseFactory{
    private final String userAgent;
    private final @Nullable
    TransferListener listener;
    private final int connectTimeoutMillis;
    private final int readTimeoutMillis;
    private final boolean allowCrossProtocolRedirects;

    /**
     * Constructs a DefaultHttpDataSourceFactory. Sets {@link
     * DefaultHttpDataSource#DEFAULT_CONNECT_TIMEOUT_MILLIS} as the connection timeout, {@link
     * DefaultHttpDataSource#DEFAULT_READ_TIMEOUT_MILLIS} as the read timeout and disables
     * cross-protocol redirects.
     *
     * @param userAgent The User-Agent string that should be used.
     */
    public CustomDataSourcesFactory(String userAgent) {
        this(userAgent, null);
    }

    /**
     * Constructs a DefaultHttpDataSourceFactory. Sets {@link
     * DefaultHttpDataSource#DEFAULT_CONNECT_TIMEOUT_MILLIS} as the connection timeout, {@link
     * DefaultHttpDataSource#DEFAULT_READ_TIMEOUT_MILLIS} as the read timeout and disables
     * cross-protocol redirects.
     *
     * @param userAgent The User-Agent string that should be used.
     * @param listener An optional listener.
     */
    public CustomDataSourcesFactory(String userAgent, @Nullable TransferListener listener) {
        this(userAgent, listener, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
                DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, false);
    }

    /**
     * @param userAgent The User-Agent string that should be used.
     * @param connectTimeoutMillis The connection timeout that should be used when requesting remote
     *     data, in milliseconds. A timeout of zero is interpreted as an infinite timeout.
     * @param readTimeoutMillis The read timeout that should be used when requesting remote data, in
     *     milliseconds. A timeout of zero is interpreted as an infinite timeout.
     * @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
     *     to HTTPS and vice versa) are enabled.
     */
    public CustomDataSourcesFactory(
            String userAgent,
            int connectTimeoutMillis,
            int readTimeoutMillis,
            boolean allowCrossProtocolRedirects) {
        this(
                userAgent,
                /* listener= */ null,
                connectTimeoutMillis,
                readTimeoutMillis,
                allowCrossProtocolRedirects);
    }

    /**
     * @param userAgent The User-Agent string that should be used.
     * @param listener An optional listener.
     * @param connectTimeoutMillis The connection timeout that should be used when requesting remote
     *     data, in milliseconds. A timeout of zero is interpreted as an infinite timeout.
     * @param readTimeoutMillis The read timeout that should be used when requesting remote data, in
     *     milliseconds. A timeout of zero is interpreted as an infinite timeout.
     * @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
     *     to HTTPS and vice versa) are enabled.
     */
    public CustomDataSourcesFactory(
            String userAgent,
            @Nullable TransferListener listener,
            int connectTimeoutMillis,
            int readTimeoutMillis,
            boolean allowCrossProtocolRedirects) {
        this.userAgent = userAgent;
        this.listener = listener;
        this.connectTimeoutMillis = connectTimeoutMillis;
        this.readTimeoutMillis = readTimeoutMillis;
        this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
    }

    @Override
    protected HttpDataSource createDataSourceInternal(
            HttpDataSource.RequestProperties defaultRequestProperties) {
        DefaultHttpDataSource defaultHttpDataSource = new DefaultHttpDataSource(userAgent, null, listener, connectTimeoutMillis,
                readTimeoutMillis, allowCrossProtocolRedirects, defaultRequestProperties);
        defaultHttpDataSource.setRequestProperty("your header", "your token");
        return defaultHttpDataSource;
    }}

Видите ли вы метод createDataSourceInternal? Я возвращаю объект DefaultHttpDataSource, инициализированный ключом заголовка и токеном defaultHttpDataSource.setRequestProperty («ваш заголовок», «ваш токен») ;. Так что теперь ваш exoplayer будет использовать URL обвинения с этим ключом заголовка и значением токена, который будет проверен вашей серверной стороной для проверки правильности запроса. Ваш плейлист hls (.m3u8) содержит URL обвинения. Exoplayer использует этот URL автоматически. Все, что вам нужно сделать, это указать игроку использовать проверочные ключи.

Итак, еще раз вот код использования Ваших пользовательских источников данных:

//ExoPlayer implementation
    //Create a default TrackSelector
    BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
    TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
    TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

    // Create a default LoadControl
    LoadControl loadControl = new DefaultLoadControl();
    //Bis. Create a RenderFactory
    RenderersFactory renderersFactory = new DefaultRenderersFactory(this);


    //Create the player
    player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
    simpleExoPlayerView = new SimpleExoPlayerView(this);
    simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);


    //Set media controller
    simpleExoPlayerView.setUseController(true);
    simpleExoPlayerView.requestFocus();

    // Bind the player to the view.
    simpleExoPlayerView.setPlayer(player);

    // Set the media source
    Uri mp4VideoUri = Uri.parse(VIDEO_URL);

    //DefaultHttpDataSource source = new DefaultHttpDataSource(Util.getUserAgent(this, "appAgent"), null);
    //source.setRequestProperty("header", "user token");

    //Measures bandwidth during playback. Can be null if not required.
    DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();

    //DefaultDataSourceFactory o = new DefaultDataSourceFactory(this, null, new DefaultHttpDataSourceFactory(Util.getUserAgent(this, "appAgent"), bandwidthMeterA));
    CustomDataSourcesFactory o = new CustomDataSourcesFactory("Exoplayer");

    //Produces DataSource instances through which media data is loaded.
    DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "PiwikVideoApp"), bandwidthMeterA);

    //Produces Extractor instances for parsing the media data.
    ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

    //FOR LIVE STREAM LINK:
    MediaSource videoSource = new HlsMediaSource(mp4VideoUri, o, 1, null, null);
    final MediaSource mediaSource = videoSource;


    player.prepare(videoSource);

Эта проблема была слишком серьезной для меня, потому что я не мог найти учебник, ресурсы или идею, чтобы решить эту проблему. Я пишу это потому, что не хочу, чтобы другие нубы, как я, страдали от этого.

Если вы не достаточно ясны, не стесняйтесь спрашивать здесь. Я буду помогать тебе дальше. У меня также есть код на стороне сервера для генерации ключа дешифрования из зашифрованного ключа AWS.

...