Java 视频查看播放前后的黑色闪光灯

Java 视频查看播放前后的黑色闪光灯,java,android,android-videoview,Java,Android,Android Videoview,我有一个视频视图,我想用它来播放电影剪辑。我这样用它来演奏它,它很管用 VideoView vv = new VideoView(this); vv.setVideoURI(Uri.parse("android.resource://cortex2.hcbj/raw/intro")); setContentView(vv); vv.start(); 然而,我在电影剪辑前后看到了一道黑色的闪光。闪光灯本身不是什么大问题,但它的黑度却是。背景是白色的,因此如果flash是白色的,或者如果它消失了,

我有一个视频视图,我想用它来播放电影剪辑。我这样用它来演奏它,它很管用

VideoView vv = new VideoView(this);
vv.setVideoURI(Uri.parse("android.resource://cortex2.hcbj/raw/intro"));
setContentView(vv);
vv.start();

然而,我在电影剪辑前后看到了一道黑色的闪光。闪光灯本身不是什么大问题,但它的黑度却是。背景是白色的,因此如果flash是白色的,或者如果它消失了,那么就可以了。

该flash来自将当前内容视图更改为另一个内容视图。您可以尝试将VideoView添加到布局xml文件中,然后使用
(VideoView)findViewById(R.id.vid)引用它
而不是
新视频视图(此)并将内容视图设置为该布局。

为什么不使用样式和主题

你能试试这个吗?这可能会有帮助

colors.xml

<drawable name="transparent">#00000000</drawable>
#00000000
styles.xml

<style name="Transparent">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">
@android:style/Animation.Translucent
</item>
<item name="android:windowBackground">@drawable/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:colorForeground">#fff</item>
</style>

真的
@android:style/Animation.半透明
@可拉伸/透明
真的
#fff
要为应用程序的所有活动设置主题,请打开AndroidManifest.xml文件并编辑标记,以包含样式名为的android:theme属性

<application android:theme="@style/Transparent">

您在哪里更改contentView(您使用哪种方法编写上述四行代码)


您应该只在
活动
onCreate()
方法中设置contentView。如果您在其他地方执行此操作(例如在按钮的回调中),则应改为启动一个新的活动。

有一种替代方法,您可以使用media controller执行此操作。下面是示例代码

videoView = (VideoView) this.findViewById(R.id.videoView);
MediaController mc = new MediaController(this);
videoView.setMediaController(mc);
videoView.setVideoURI(Uri.parse("http://c421470.r70.cf2.rackcdn.com/video_5983079.m4v"));
videoView.start();
videoView.requestFocus(); 

试试这个。

今天,我遇到了同样的问题,并找到了一个非常糟糕的解决方法:我意识到可以在
视频视图上设置背景色/可绘制,这样可以在视频表面上混合,并使其完全隐藏。但这仅在基础视频仍在播放时有效,而不是在停止时(无论是在正常结束时还是在调用
stopPlayback()
时),否则您将再次看到黑色闪烁。也不能在开始时设置背景,否则视频将从一开始就完全隐藏

所以对我来说,唯一合乎逻辑的步骤就是在我开始视频之前发布一个延迟事件——因为我知道视频的长度,所以我让这个事件在正常结束前几毫秒发生。我拍摄了VLC中最后一帧的屏幕截图,然后将其混合如下:

private void startVideo()
{
    introVideo.setBackgroundDrawable(null);
    introVideo.postDelayed(new Runnable() {
        public void run()
        {
            if (!introVideo.isPlaying())
                return;

            introVideo.setBackgroundResource(R.drawable.video_still_image);
            // other stuff here, for example a custom transition to
            // another activity
        }
    }, 7500); // the video is roughly 8000ms long
    introVideo.start();
}
但这还不够,因为当视频实际结束时,我仍然会看到一个短的黑屏闪烁,因此我还必须将静止图像设置为包含视频的容器的背景(在我的情况下,这是活动的布局):


此活动以全屏显示,视频(大部分)缩放到总屏幕大小(屏幕1024x600,视频960x640)。我说的主要原因是,由于某种未知的原因,布局的背景图像在顶部混合了大约10px。这是我最后一次使用黑客软件,将视频容器
-10dip
移动到顶部的空白处


这在我的Galaxy标签上看起来棒极了,我不敢在SGS2手机上测试它,尽管…

我解决这一恶魔般的错误的方法是在视频视图顶部使用一个空白视图,背景颜色可供选择

<View
        android:id="@+id/blankView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@color/white" />
这让我摆脱了最初的黑色闪光。然后在最后的黑色闪光中,我做了如下操作:

        video = (VideoView) findViewById(R.id.video);
        // set the video URI, passing the vSourse as a URI
        video.setVideoURI(Uri.parse(vSource));
        video.setZOrderOnTop(false);

        SurfaceHolder sh = video.getHolder();
        sh.setFormat(PixelFormat.TRANSPARENT);

        ctlr = new BCDMediaController(this);
        ctlr.setMediaPlayer(video);
        video.setMediaController(ctlr);
        video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {              
            @Override
            public void onCompletion(MediaPlayer mp) {
                closeActivity();
            }
        });

        blankView = findViewById(R.id.blankView);

        video.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {    
                blankView.postDelayed(new Runnable() {
                        public void run()
                        {
                            blankView.setVisibility(View.GONE);
                        }
                    }, 500);                    
            }
        });

        video.start();
        video.requestFocus();
private void closeActivity() {  
blankView.setVisibility(View.VISIBLE);        
    blankView.postDelayed(new Runnable() {
        public void run()
        {
            video.setOnCompletionListener(null);
            video.stopPlayback();
            video.suspend();
            VideoPlayerViewController.this.finish();
        }
    }, 1);    
}

我最后不得不做一些与@tommyd非常相似的事情,以避免在视频开始和结束时出现黑色的surfaceView flash。然而,我发现在许多手机上,设置/取消videoView的可绘制背景并不是立即发生的。在我打电话设置背景和实际显示背景之间可能会有大约半秒的延迟

我最后做的是创建一个自定义的SurfaceView,显示单一的纯色,然后将其覆盖在视频视图的顶部,并使用SurfaceView.setzordermediagoverlay()

我的定制SurfaceView主要了解以下信息:

在承载视图的父活动中:

    mVideoView = (VideoView)findViewById(R.id.video_view);
    mVideoMask = (SolidSurfaceView)findViewById(R.id.video_mask);
    mVideoMask.setColor(Color.BLUE);
然后,您可以执行类似于
mvideosk.setVisibility(View.GONE)
的操作来隐藏掩码,或者
mvideosk.setVisibility(View.VISIBLE)
来显示掩码(并隐藏黑屏视频视图)


在我在各种手机上进行的实验中,这种方法可以非常快速地显示/隐藏视频掩码,而不是设置/消除背景。

另一种可能适用于搜索此问题的人的解决方案:

在我的例子中,视频是应用程序中的一个资源(也就是说,我知道关于它的一切,它不会改变),它的最后500毫秒是同一帧,所以我最终做了以下工作:

mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.splash));
mVideoView.start();

findViewById(android.R.id.content).postDelayed(new WaitForSplashScreenToFinish(), mVideoView.getDuration() - 1000);
引用的类是:

private class WaitForSplashScreenToFinish implements Runnable {
    @Override
    public void run() {
        if (mVideoView.isPlaying() && mVideoView.getCurrentPosition() >= mVideoView.getDuration() - 500) {
            mVideoView.pause();

            // Now do something else, like changing activity
        } else {
            findViewById(android.R.id.content).postDelayed(this, 100);
        }
    }
}
说明:启动视频后,我立即创建了一个Runnable,并将其保存到根视图(
android.R.id.content
)中,以视频的持续时间减去我愿意暂停视频的长度(以及一个充足的缓冲区,因为postDelayed不能保证完全在请求的时间之后播放)

然后,runnable检查视频是否在暂停时间到达,如果是,则暂停视频并执行我们希望它执行的任何其他操作。如果没有,它会再次运行postDelayed,时间会缩短(在我的例子中是100毫秒,但可能更短)


诚然,这远不是一个理想的解决方案,但它可能会帮助某些人解决一个特定的问题,类似于让我绊倒了半天的问题:)

我也有同样的问题,我可以用白色代替黑色。。我尝试了以上所有的解决方案,得出了以下结论

vv.setBackgroundColor(Color.WHITE);
vv.postDelayed(new Runnable() {
                @Override
                public void run() {
                    vv.setVideoURI(videoUri);
                }
            }, 100);
vv.postDelayed(new Runnable() {
                @Override
                public void run() {
                    vv.setBackgroundColor(Color.TRANSPARENT);
                }
            }, 300);
            vv.requestFocus();
            vv.start();

延迟我的视频400毫秒开始从白色淡出对我来说很有魅力

我知道这是个老问题,但如果你能给MediaPlayer的听众添加一些代码,答案很简单。事实证明,VideoView的setBackgroundColor会改变前景色()。
所以你唯一要做的就是
private class WaitForSplashScreenToFinish implements Runnable {
    @Override
    public void run() {
        if (mVideoView.isPlaying() && mVideoView.getCurrentPosition() >= mVideoView.getDuration() - 500) {
            mVideoView.pause();

            // Now do something else, like changing activity
        } else {
            findViewById(android.R.id.content).postDelayed(this, 100);
        }
    }
}
vv.setBackgroundColor(Color.WHITE);
vv.postDelayed(new Runnable() {
                @Override
                public void run() {
                    vv.setVideoURI(videoUri);
                }
            }, 100);
vv.postDelayed(new Runnable() {
                @Override
                public void run() {
                    vv.setBackgroundColor(Color.TRANSPARENT);
                }
            }, 300);
            vv.requestFocus();
            vv.start();
    mMovieView.setBackgroundDrawable(bg);
    mMovieView.start();

    final int kPollTime= 25;
    mMovieView.postDelayed(new Runnable() {

        private final int kStartTransitionInThreshold= 50;
        private final int kStartTransitionOutThreshold= 250;

        private boolean mTransitioned= false;
        @Override
        public void run() {
            if (mMovieView.isPlaying()) {
                if (mMovieView.getCurrentPosition() > kStartTransitionInThreshold && !mTransitioned) {
                    mMovieView.setBackgroundDrawable(null); // clear to video
                    mTransitioned= true;
                }

                if (mMovieView.getDuration() - mMovieView.getCurrentPosition() < kStartTransitionOutThreshold)
                    mMovieView.setBackgroundDrawable(bg);
            }

            mMovieView.postDelayed(this, kPollTime); // come back in a bit and try again
        }
    }, kPollTime);
@Override
 protected void onDestroy() {
     super.onDestroy();
         player.pause();
     if(player!=null)player.release();
     player = null;
     videoSurface = null;
     controller = null;

 }
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(final MediaPlayer mediaPlayer) {
                mVideoView.start();


                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                        while (mediaPlayer.isPlaying()) {
                            Log.d("MainActivity", "position " + mediaPlayer.getCurrentPosition());
                            if (mediaPlayer.getCurrentPosition() == 0) {
                                videoStillImageView.setVisibility(View.VISIBLE);
                            } else {
                                videoStillImageView.setVisibility(View.GONE);


                                break;
                            }
                        }

                    }
                });
            }
        }
    });