android - 如何显示较小的视频文件比较大的视频文件流速度更快?
问题描述
我在 Android 中有一个简单的视频播放器应用程序,可以播放两个给定 URL 的视频。一个是较小的 mp4 文件,另一个是较大的文件。基本上,我想展示更小的 mp4 缓冲区和播放速度更快,这仅仅是因为它的尺寸更小并且需要下载更多的内容。但是我在展示这个概念时遇到了问题,而我所做的并不是那样的。我在第一个播放器之后初始化第二个播放器,并获得时间来缓冲 100% 的 URL 视频并将其显示在每个播放器下方。显然它没有显示我打算证明的内容。
我在这里做错了什么?有什么方法可以证明这个概念?
这是我的简单代码:
package com.example.videoplayer;
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.AttributeSet;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
public class MainActivity extends AppCompatActivity {
//https://dl5.webmfiles.org/video-h264.mkv
//https://s3.amazonaws.com/x265.org/video/BigBuckBunny_2000hevc.mp4
private static final String VIDEO_SAMPLE =
"https://dl5.webmfiles.org/video-h264.mkv";
private static final String VIDEO_SAMPLE2 =
"https://dl5.webmfiles.org/video-h265.mkv";
private VideoView vw1, vw2;
private TextView mBufferingTextView,mBufferingTextView2;
// Current playback position (in milliseconds).
private int mCurrentPosition = 0;
// Tag for the instance state bundle.
private static final String PLAYBACK_TIME = "play_time";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vw1 = findViewById(R.id.videoView1);
vw2 = findViewById(R.id.videoView2);
mBufferingTextView = findViewById(R.id.buffering_textview);
mBufferingTextView2 = findViewById(R.id.buffering_textview2);
if (savedInstanceState != null) {
mCurrentPosition = savedInstanceState.getInt(PLAYBACK_TIME);
}
// Set up the media controller widget and attach it to the video view.
// MediaController controller = new MediaController(vw1.getContext());
// controller.setMediaPlayer(vw1);
// vw1.setMediaController(controller);
}
@Override
protected void onStart() {
super.onStart();
// Load the media each time onStart() is called.
initializePlayer();
initializePlayer2();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
// Media playback takes a lot of resources, so everything should be
// stopped and released at this time.
// releasePlayer();
}
private void initializePlayer() {
// Show the "Buffering..." message while the video loads.
mBufferingTextView.setVisibility(VideoView.VISIBLE);
// Buffer and decode the video sample.
long t0 = System.currentTimeMillis();
Uri videoUri = Uri.parse(VIDEO_SAMPLE);
vw1.setVideoURI(videoUri);
// Listener for onPrepared() event (runs after the media is prepared).
vw1.setOnPreparedListener(
new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
// Hide buffering message.
// mBufferingTextView.setVisibility(VideoView.INVISIBLE);
// Restore saved position, if available.
// if (mCurrentPosition > 0) {
// vw1.seekTo(mCurrentPosition);
// } else {
// // Skipping to 1 shows the first frame of the video.
// vw1.seekTo(1);
// }
// Start playing!
vw1.start();
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
boolean buffered = false;
@Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
if(i==100 && !buffered) {
long t1 = System.currentTimeMillis();
mBufferingTextView.setText((t1 - t0) + ", " + i + " ");
buffered = true;
}
}
});
}
});
// Listener for onCompletion() event (runs after media has finished
// playing).
vw1.setOnCompletionListener(
new MediaPlayer.OnCompletionListener()
{
@Override
public void onCompletion (MediaPlayer mediaPlayer){
Toast.makeText(MainActivity.this,
"Completed",
Toast.LENGTH_SHORT).show();
// Return the video position to the start.
vw1.seekTo(0);
}
});
}
private void initializePlayer2() {
// Show the "Buffering..." message while the video loads.
mBufferingTextView2.setVisibility(VideoView.VISIBLE);
// Buffer and decode the video sample.
long t0 = System.currentTimeMillis();
Uri videoUri = Uri.parse(VIDEO_SAMPLE2);
vw2.setVideoURI(videoUri);
// Listener for onPrepared() event (runs after the media is prepared).
vw2.setOnPreparedListener(
new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
// Hide buffering message.
// mBufferingTextView.setVisibility(VideoView.INVISIBLE);
// Restore saved position, if available.
// if (mCurrentPosition > 0) {
// vw2.seekTo(mCurrentPosition);
// } else {
// // Skipping to 1 shows the first frame of the video.
// vw2.seekTo(1);
// }
// Start playing!
vw2.start();
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
boolean buffered = false;
@Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
if(i==100 && !buffered) {
long t1 = System.currentTimeMillis();
mBufferingTextView2.setText((t1 - t0) + ", " + i + " ");
buffered = true;
}
}
});
}
});
// Listener for onCompletion() event (runs after media has finished
// playing).
vw2.setOnCompletionListener(
new MediaPlayer.OnCompletionListener()
{
@Override
public void onCompletion (MediaPlayer mediaPlayer){
Toast.makeText(MainActivity.this,
"Completed",
Toast.LENGTH_SHORT).show();
// Return the video position to the start.
vw2.seekTo(0);
}
});
}
// Release all media-related resources. In a more complicated app this
// might involve unregistering listeners or releasing audio focus.
private void releasePlayer() {
vw1.stopPlayback();
}
}
和布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
>
<!-- adding VideoView to the layout -->
<VideoView
android:id="@+id/videoView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/buffering_textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Buffering..."
android:layout_margin="8dp"
android:textSize="18sp"
android:textStyle="bold"
/>
<VideoView
android:id="@+id/videoView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/buffering_textview2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Buffering..."
android:layout_margin="8dp"
android:textSize="18sp"
android:textStyle="bold"
/>
</LinearLayout>
解决方案
我检查了代码中的 2 个视频:视频 1 的比特率为 4 MBPS,视频 2 的比特率为 2 MBPS。(我用https://ffprobe.a.video测试了两者以获得比特率)。
如果测试仪使用 Wi-Fi,并且网络吞吐量为 10 MBPS,则两个视频都可以毫无问题地下载和播放。
IDK 如何在 Android 应用程序中节流。如果此应用仅用于演示目的,请使用 Charles Proxy 设置笔记本电脑以限制网络,并通过 Charles Proxy 连接 android 设备。
其他演示方式:获取“非常大”的视频。就像 20(或 40 或 50)MBPS。然后创建一个 5(或 10)MBPS 版本。然后,您可能会在没有节流的“传统”网络连接上看到更多缓冲。
注意:您的一个视频是 h264,另一个是 h265。如果你想做一个 apples:apples,我建议你让两个视频的格式完全相同——只是为了减少实验中的变量数量。
推荐阅读
- c# - 在 .NET Core MVC 3.1 中为坐标传递双精度值
- terminal - 修补时自动是命令?
- powershell - json格式的Powershell输出
- c# - 如何将值从datagridview传递到文本框
- swift - 我不确定为什么我不断收到错误“(AnyObject)->()”类型的值没有成员“currentTitle”
- python - 如何使用 GAN 生成人类活动识别数据?
- python - 如何为同一数据帧的不同组计算一个简单的函数?
- python - pycharm virualenv 从子目录导入类
- python - 套接字错误:111 [.connect((host, port))]
- json - HttpMessageNotReadableException:JSON 解析错误