使用加密密钥在 exoplayer 中播放加密的 hls
Play encrypted hls in exoplayer using encrypted keys
我正在尝试使用 .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
我找到了解决办法。您需要做的技巧是创建您自己的自定义数据源。您需要创建一个扩展 HttpDataSource.BaseFactory 的 class 并从 DefaultHttpDataSourceFactory 添加一些代码。我知道这听起来很疯狂,但我已经通过这种方式解决了。别担心,我在这里粘贴了该自定义的全部代码 class。
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 object 使用 header 密钥和令牌 defaultHttpDataSource.setRequestProperty("your header", "your token"); 初始化。所以现在你的 exoplayer 将使用这个 header 键和令牌值来攻击 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 加密密钥生成解密密钥。
我正在尝试使用 .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
我找到了解决办法。您需要做的技巧是创建您自己的自定义数据源。您需要创建一个扩展 HttpDataSource.BaseFactory 的 class 并从 DefaultHttpDataSourceFactory 添加一些代码。我知道这听起来很疯狂,但我已经通过这种方式解决了。别担心,我在这里粘贴了该自定义的全部代码 class。
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 object 使用 header 密钥和令牌 defaultHttpDataSource.setRequestProperty("your header", "your token"); 初始化。所以现在你的 exoplayer 将使用这个 header 键和令牌值来攻击 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 加密密钥生成解密密钥。