首页 > 解决方案 > 如何显示较小的视频文件比较大的视频文件流速度更快?

问题描述

我在 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>

标签: androidvideovideo-streamingvideo-encodingmpeg-dash

解决方案


我检查了代码中的 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,我建议你让两个视频的格式完全相同——只是为了减少实验中的变量数量。


推荐阅读