我有一个使用AES算法加密的视频文件,但我需要在播放视频视图之前解密视频。问题是解密视频所需的时间太长。有什么办法我可以做到吗。
更新:
E/ExoPlayerIMIPER内部:播放错误com.google.android.exoplayer2.upstream.2. ExoPlaybackException:源错误在com.google.android.exoplayer2. ExoPlayerIMIPInternal.handle消息(ExoPlayerIMIPInternal.java:579)在android.os.Handler.dispatch消息(Handler.java:102)在android.os.Looper.loop(Looper.java:164)在android.os.HandlerThread.run(HandlerThread.java:65)由以下原因引起:com.google.android.exoplayer2.source.无法识别InputFormatException:没有可用的提取器(FragmentedMp4Extractor, Mp4Extractor, FlvExtractor, FlacExtractor, WavExtractor, AmrExtractor, PsExtractor, OggExtractor, TsExtractor, MatroskaExtractor, AdtsExtractor, Ac3Extractor, Ac4Extractor, Mp3Extractor, JpegExtractor)在com.google.android.exoplayer2.source.BundledExtractorsAdapter.init(BundledExtractorsAdapter.java:92)在com.google.android.exoplayer2.source.ProgressiveMedia$Extracting Loadable.load(ProgressiveMediaPeriod.java:1026)在com.google.android.exoplayer
给你。我不知道它是否有效,但它应该:
import android.net.Uri;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.BaseDataSource;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.FileDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import static java.lang.Math.min;
public class EncryptedFileDataSource extends BaseDataSource {
public static class EncryptedFileDataSourceException extends IOException {
public EncryptedFileDataSourceException(Throwable cause) {
super(cause);
}
public EncryptedFileDataSourceException(String message, IOException cause) {
super(message, cause);
}
}
/**
* {@link DataSource.Factory} for {@link EncryptedFileDataSource} instances.
*/
public static final class Factory implements DataSource.Factory {
@Nullable
private TransferListener listener;
private byte[] key;
private String transformation;
public Factory() {
this(null, null);
}
public Factory(byte[] key) {
this(key, null);
}
public Factory(byte[] key, String transformation) {
setKey(key);
setTransformation(transformation);
}
public void setKey(byte[] key) {
if (key == null) {
return;
}
this.key = key;
}
public void setTransformation(String transformation) {
if (transformation == null) {
transformation = "AES/ECB/PKCS5Padding";
}
this.transformation = transformation;
}
/**
* Sets a {@link TransferListener} for {@link EncryptedFileDataSource} instances created by this factory.
*
* @param listener The {@link TransferListener}.
* @return This factory.
*/
public Factory setListener(@Nullable TransferListener listener) {
this.listener = listener;
return this;
}
@Override
public EncryptedFileDataSource createDataSource() {
EncryptedFileDataSource dataSource = new EncryptedFileDataSource(key, transformation);
if (listener != null) {
dataSource.addTransferListener(listener);
}
return dataSource;
}
}
@Nullable
private RandomAccessFile file;
@Nullable
private Uri uri;
private long bytesRemaining;
private boolean opened;
private byte[] key;
private String transformation;
private Cipher cipher;
private byte[] tmpBuffer;
private EncryptedFileDataSource(byte[] key, String transformation) {
super(false);
setKey(key);
setTransformation(transformation);
}
public void setKey(byte[] key) {
this.key = key;
}
public void setTransformation(String transformation) {
this.transformation = transformation;
}
@Override
public long open(@NonNull DataSpec dataSpec) throws EncryptedFileDataSourceException {
try {
byte[] key = this.key;
String transformation = this.transformation;
Uri uri = dataSpec.uri;
this.uri = uri;
transferInitializing(dataSpec);
if (key != null && transformation != null) {
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.DECRYPT_MODE, keySpec);
}
this.file = openLocalFile(uri);
file.seek(dataSpec.position);
bytesRemaining = dataSpec.length == C.LENGTH_UNSET ? file.length() - dataSpec.position
: dataSpec.length;
if (bytesRemaining < 0) {
throw new EOFException();
}
} catch (IOException
| NoSuchPaddingException
| NoSuchAlgorithmException
| InvalidKeyException e) {
throw new EncryptedFileDataSourceException(e);
}
opened = true;
transferStarted(dataSpec);
return bytesRemaining;
}
@Override
public int read(@NonNull byte[] buffer, int offset, int readLength) throws EncryptedFileDataSourceException {
if (readLength == 0) {
return 0;
} else if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT;
} else {
int bytesRead, bytesStored;
try {
int length = (int) min(bytesRemaining, readLength);
Cipher cipher = this.cipher;
if (cipher != null) {
tmpBuffer = resize(tmpBuffer, length);
bytesRead = castNonNull(file).read(tmpBuffer, 0, length);
bytesStored = cipher.doFinal(tmpBuffer, 0, length, buffer, offset);
} else {
bytesStored = bytesRead = castNonNull(file).read(buffer, offset, length);
}
} catch (IOException
| BadPaddingException
| IllegalBlockSizeException
| ShortBufferException e) {
throw new EncryptedFileDataSourceException(e);
}
if (bytesRead > 0) {
bytesRemaining -= bytesRead;
bytesTransferred(bytesRead);
}
return bytesStored;
}
}
@Nullable
@Override
public Uri getUri() {
return uri;
}
@Override
public void close() throws EncryptedFileDataSourceException {
uri = null;
try {
if (file != null) {
file.close();
}
} catch (IOException e) {
throw new EncryptedFileDataSourceException(e);
} finally {
file = null;
key = null;
transformation = null;
cipher = null;
if (opened) {
opened = false;
transferEnded();
}
byte[] tmpBuffer = this.tmpBuffer;
this.tmpBuffer = null;
if (tmpBuffer != null) {
for (int i = tmpBuffer.length - 1; i >= 0; i -= 2) {
tmpBuffer[i] = (byte) 0;
}
}
}
}
static byte[] resize(byte[] b, int newLen) {
if (newLen < 0) return b;
if (b == null || b.length < newLen) {
return new byte[newLen];
} else return b;
}
private static RandomAccessFile openLocalFile(Uri uri) throws FileDataSource.FileDataSourceException {
try {
return new RandomAccessFile(Assertions.checkNotNull(uri.getPath()), "r");
} catch (FileNotFoundException e) {
if (!TextUtils.isEmpty(uri.getQuery()) || !TextUtils.isEmpty(uri.getFragment())) {
throw new FileDataSource.FileDataSourceException(
String.format(
"uri has query and/or fragment, which are not supported. Did you call Uri.parse()"
+ " on a string containing '?' or '#'? Use Uri.fromFile(new File(path)) to"
+ " avoid this. path=%s,query=%s,fragment=%s",
uri.getPath(), uri.getQuery(), uri.getFragment()),
e);
}
throw new FileDataSource.FileDataSourceException(e);
}
}
}
这样使用:
public void playVideo(Uri uri, byte[] key, @Nullable String transformation) {
playVideo(MediaItem.fromUri(uri), key, transformation);
}
public void playVideo(MediaItem media, byte[] key, @Nullable String transformation) {
ExoPlayer player = new SimpleExoPlayer.Builder(this).build();
playerView.setPlayer(player);
try {
DataSource.Factory dataSourceFactory = new EncryptedFileDataSource.Factory(key, transformation);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
ProgressiveMediaSource.Factory progressiveFactory = new ProgressiveMediaSource.Factory(
dataSourceFactory,
extractorsFactory
);
ProgressiveMediaSource mediaSource = progressiveFactory.createMediaSource(media);
player.setMediaSource(mediaSource);
//player.setMediaSource(mediaSource, startPositionMs: long);
//player.setMediaSource(mediaSource, resetPosition: boolean);
player.setPlayWhenReady(true);
} catch (Exception e) {
e.printStackTrace();
}
}
我使用了以下来源:
当文件存储在本地时,您可能根本不需要对其进行加密。andorid中的本地文件存储对用户或任何其他应用程序都不可见。只有你的应用程序可以访问存储,所以你不需要担心用户阅读机密数据。
编辑:正如我刚刚看到您最近对本地的评论,您的意思是在设备上。您可以将视频保存在内部存储中,除了您的应用程序之外,没有其他内容可以访问。看看纪录片:https://developer.android.com/training/data-storage/app-specific
在linux盒子上,我有一个用openssl加密的MP4视频: 请注意,这是一个练习,算法的强度并不重要。 该文件被发送到Android应用程序,我正在尝试使用ExoPlayer播放它。 我之前已经对文本文件进行了一些测试,以确保解密工作正常 关于ExoPlayer,在AiscipherDataSource、AiscipherDataSink、SimpleCache等之间有点势不可挡。我无法找到一
我一直试图在ShakaPlayer中播放加密的。WebM媒体文件,但没有太多成功,我在这里寻求任何经历过这一点的人的建议。如果这个很棒的开发人员社区有人能在这里指导我,那就太好了。 第1轮-我所尝试的(编码和虚线): 使用ffmpeg.将.mp4文件编码为多流Video.webm(VP9)&单流Audio.webm(Vorbis)文件 使用webm_tools/webm_dash_manifest
问题内容: 我有问题 我想在pygame中加载和播放视频,但它没有开始。我唯一看到的是黑屏。这是我的代码: 你能帮助我吗?? 问题答案: 您实际上并没有将其发送到屏幕。您也没有使用时钟对象,因此它将尽可能快地播放。尝试这个: 我只是从评论中提供的链接中获得了MELT.MPG。您应该能够简单地为您要播放的实际MPG切换出该字符串,它就可以工作…也许。
我已经成功地上传了一个音频文件(3GP)到谷歌驱动器。 现在我希望能够在应用程序中播放该文件。 Google Drive API只允许获取存储在那里的文件的输入流。 在我的情况下,输入的所有MediaPlayer功能都不可用,这只是InputSteam: 我知道我可以将文件从谷歌驱动器保存到缓存中并播放它,但我想避免存储处理,并在飞行中播放文件。 我试图搜索这个问题,只发现可能使用AudioTra
我检查过: 我查看了这个链接,上面有一个答案,说你必须将视频转换成块,并将块保存到firebase存储区,然后加载它们: 但我在这里迷失了: 谢谢你的努力。
问题内容: 我要实现以下目标。 目的是使用户能够从他/她的硬盘驱动器中选择文件。 不上传的原因当然是传输成本和存储配额。没有理由保存文件。 可能吗? 问题答案: 可以播放本地视频文件。 通过元素选择文件时: “更改”事件被触发 从获取第一个File对象 制作指向File对象的对象URL 将对象URL设置为属性 靠后看