如何显示较小的视频文件比较大的视频文件流速度更快?

Posted

技术标签:

【中文标题】如何显示较小的视频文件比较大的视频文件流速度更快?【英文标题】:How to show that a smaller video file streams fasters than a bigger video file? 【发布时间】:2021-11-13 07:24:04 【问题描述】:

我在 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_
    android:layout_
    tools:context=".MainActivity"
    android:orientation="vertical"
    >

    <!-- adding VideoView to the layout -->
    <VideoView
        android:id="@+id/videoView1"
        android:layout_
        android:layout_ />

    <TextView
        android:id="@+id/buffering_textview"
        android:layout_
        android:layout_
        android:text="Buffering..."
        android:layout_margin="8dp"
        android:textSize="18sp"
        android:textStyle="bold"
        />

    <VideoView
        android:id="@+id/videoView2"
        android:layout_
        android:layout_ />



    <TextView
        android:id="@+id/buffering_textview2"
        android:layout_
        android:layout_
        android:text="Buffering..."
        android:layout_margin="8dp"
        android:textSize="18sp"
        android:textStyle="bold"
        />

</LinearLayout>

【问题讨论】:

播放速度与文件大小无关。每秒帧数相同。 是的,但我的意思是从网络下载和缓冲是不同的。只是玩家需要下载更多内容才能开始播放。 那么您可以更好地重新编写和编辑您的帖子,因为没有什么要尽快开始播放。编码与它有什么关系?我们可以在这张图片上看到什么?很混乱。 @TinaJ 如果我的问题是正确的,您可以缓冲固定的视频持续时间,比如说每个视频的 5 秒,并显示下载前 5 秒需要 x 秒的祝酒词。或者您可以创建应用程序以使其他类型的播放变得可怕。就像在播放过程中加载... 为什么不尝试限制网络速度,为了更好地欣赏缓冲速度,也尝试显示缓冲进度条,就像 YouTube 那样 【参考方案1】:

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

【讨论】:

Tnx。是的,所以 bc 一个视频具有更大的比特率,缓冲第一个视频所需的“时间”应该更大,无论播放器是否可以播放它们。是的 - 我的观点是显示其较小尺寸的 h265 bc 需要更少的时间来缓冲和更快地加载。

以上是关于如何显示较小的视频文件比较大的视频文件流速度更快?的主要内容,如果未能解决你的问题,请参考以下文章

ffmpeg 命令以较小的文件大小以适当的比特率进行更快的编码

为啥较大的视频流比较小的视频更快?

三个技巧,将Docker镜像体积减小90%

将一个大的 json 文件拆分为多个较小的文件

FFmpeg:如何有效地分割视频?

iOS 分享扩展 - 发送大视频