Skip to content

Video Playback and Recording

Ansh Sachdeva edited this page Oct 13, 2019 · 22 revisions

Overview

In Android apps, there are often cases where we need to play video files. Checking the Supported Media Formats we can see that several video formats (H.264, MPEG-4) are playable by default.

In this guide we will take a look at how to play video content using the VideoView and capture video with the MediaRecorder.

Video Playback

Playing Local Video

Playing local video in a supported format can be done using the VideoView. First, setup the VideoView in your layout:

<VideoView
    android:id="@+id/video_view"
    android:layout_width="320px"
    android:layout_height="240px" />

Next, we can store local files such as small_video.mp4 in res/raw/small_video.mp4 and than play the video in the view with:

VideoView mVideoView = (VideoView) findViewById(R.id.video_view);
mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() +"/"+R.raw.small_video));
mVideoView.setMediaController(new MediaController(this));
mVideoView.requestFocus();
mVideoView.start();

See this tutorial for playing a video full-screen with a VideoView. See this other edumobile tutorial for a more detailed look at using VideoView.

Playing Streaming Video

To play back remote video in a supported format, we can still use the VideoView. First, setup the correct permissions in the Android Manifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

Now, we can play remote video with:

final VideoView mVideoView = (VideoView) findViewById(R.id.video_view);
mVideoView.setVideoPath("http://techslides.com/demos/sample-videos/small.mp4");
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(mVideoView);
mVideoView.setMediaController(mediaController);
mVideoView.requestFocus();
mVideoView.setOnPreparedListener(new OnPreparedListener() {
    // Close the progress bar and play the video
    public void onPrepared(MediaPlayer mp) {
        mVideoView.start();
    }
});

You can see a more complete example of remote streaming with this androidbegin tutorial.

VideoView Controls

We can remove the VideoView media controls with:

mVideoView.setMediaController(null)

We can hide or show the media UI controls at runtime with:

// Get instance to media controller
MediaController controller = new MediaController(this);
videoHolder.setMediaController(controller);
// Hide the controller
controller.setVisibility(View.GONE);
// Show the controller 
controller.setVisibility(View.VISIBLE);

VideoView Limitations and Improved Libraries

VideoView should not be embedded in a ListView or any scrolling view due to a known bug with Android. Instead of using a VideoView which extends SurfaceView, in order to enable scrolling we need to use a TextureView instead. The easiest workaround is to use a library such as Android-ScalableVideoView, VideoPlayerManager, or fenster.

You can read about how fenster was developed as well. If you are using fenster and running into a permissions error related to write_settings on an Android >= 6.0 device, check out this snippet as a workaround.

Streaming from YouTube

We can use the [YouTube Android Player API] (https://developers.google.com/youtube/android/player/) to play YouTube videos within an Android app.

Refer to the Streaming Youtube Videos with YouTubePlayerView guide for detailed instructions.

Streaming Via Exoplayer.

Exoplayer is an Advanced Video Library by Google that is aimed to be more customizable and flexible than the traditional video_view and MediaPlayer approach. Read more about it here.

Adding it to a project

  • in your gradle files, add these lines:
//project's build.gradle
repositories {
    google()
    jcenter()
}

//app/build.gradle
android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    ...
    implementation 'com.google.android.exoplayer:exoplayer:2.10.5' //current version as of oct,2019
    //there is also an option to import only specific modules
}

Streaming a video via Exoplayer

The basic steps for playing a video(that is available on some server on the internet) via Exoplayer are :

  1. add the <player_view> in xml and create its instance: This will be the view on which the video will be rendered.
  2. create a Player instance : This will be the main Handler behind all the streaming , decoding and rendering of bitstreams
  3. create a MediaSource Instance: This is the Class associated with the Uri of the content you intend to play
  4. attach playerView to player
  5. start video playback via absPlayerInternal.setPlayWhenReady(true); :this will automatically start playing video as soon as the video is available.( To control playback manually, simply pass false, the playback will then only start when user presses the play button .
  • in your activity or framgment's xml file,add these lines:
 <com.google.android.exoplayer2.ui.PlayerView
        android:id="@+id/pv_main"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        />
<!-- there are many customization attributes available like app:auto_show="true" or app:ad_marker_color="@color/colorAccent", etc which can be either used via xml or from java -->
  • in your activity or fragment's java file, add these lines:
     SimpleExoPlayer absPlayerInternal;PlayerView pvMain;

     protected void onCreate(Bundle savedInstanceState) {
        ...
        
        String CONTENT_URL = "https://www.radiantmediaplayer.com/media/bbb-360p.mp4";
        
        int appNameStringRes = R.string.app_name;

        pvMain = findViewById(R.id.pv_main); // creating player view
        
        TrackSelector trackSelectorDef = new DefaultTrackSelector();
        absPlayerInternal = ExoPlayerFactory.newSimpleInstance(this, trackSelectorDef); //creating a player instance
        
        String userAgent = Util.getUserAgent(this, this.getString(appNameRes));
        DefaultDataSourceFactory defdataSourceFactory = new DefaultDataSourceFactory(this,userAgent);
        Uri uriOfContentUrl = Uri.parse(CONTENT_URL);
        MediaSource mediaSource = new ProgressiveMediaSource.Factory(defdataSourceFactory).createMediaSource(uriOfContentUrl);  // creating a media source

        absPlayerInternal.prepare(mediaSource);
        absPlayerInternal.setPlayWhenReady(true); // start loading video and play it at the moment a chunk of it is available offline

        pvMain.setPlayer(absPlayerInternal); // attach surface to the view
    }
  • For Pausing the video
    private void pausePlayer(SimpleExoPlayer player) {
        if (player != null) {
            player.setPlayWhenReady(false);
        }
    }
  • For resuming the video:
    private void playPlayer(SimpleExoPlayer player) {
        if (player != null) {
            player.setPlayWhenReady(true);
        }
    }
  • for stopping the video :
    private void stopPlayer(){
        pv.setPlayer(null);
        absPlayer.release();
        absPlayer = null;
    }
  • For Seeking the video to some point:
    private void seekTo(SimpleExoPlayer player, long positionInMS) {
        if (player != null) {
            player.seekTo(positionInMS);
        }
    }

Extras

  • To silence video's volume, simply do : absPlayerInternal.setVolume(0f)

  • The <PlayerView> has a built in Video controller that can be toggled using pvMain.setUseController(/*true or false*/) and other functions. But if you want, you can also add an external exoplayer's controller view called <PlayerControlView>. exoplayer image

  • Exoplayer has many useful extensions , some of which are mentioned here .

Capturing Video

Using Intents

Capturing video can be done using intents to capture video using the camera. First, let's setup the necessary permissions in AndroidManifest.xml (Note: The permissions model has changed starting in Marshmallow. If your targetSdkVersion >= 23 and you are running on a Marshmallow (or later) device, you may need to enable runtime permissions. You should also read more about the runtime permissions changes):

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Next, we can trigger recording video by starting an intent triggering a video capture action:

private static final int VIDEO_CAPTURE = 101;
Uri videoUri;
public void startRecordingVideo() {
    if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        File mediaFile = new File(
           Environment.getExternalStorageDirectory().getAbsolutePath() + "/myvideo.mp4");
        videoUri = Uri.fromFile(mediaFile);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri);
        startActivityForResult(intent, VIDEO_CAPTURE);
    } else {
        Toast.makeText(this, "No camera on device", Toast.LENGTH_LONG).show();
    }
}

and then we need to manage the onActivityResult for when the video has been captured:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == VIDEO_CAPTURE) {
        if (resultCode == RESULT_OK) {
            Toast.makeText(this, "Video has been saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();
            playbackRecordedVideo();
        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(this, "Video recording cancelled.",  Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "Failed to record video",  Toast.LENGTH_LONG).show();
        }
    }
}

public void playbackRecordedVideo() {
    VideoView mVideoView = (VideoView) findViewById(R.id.video_view);
    mVideoView.setVideoURI(videoUri);
    mVideoView.setMediaController(new MediaController(this));
    mVideoView.requestFocus();
    mVideoView.start();
}

For a more detailed look, check out the techtopia tutorial on video recording.

Using MediaRecorder

If we want to record video from within an app directly, we'll want to use the MediaRecorder. We can find good references for using the recorder in the following resources below:

For more advanced usage, see this video recording and processing guide.

Configuring Encoding

The MediaRecorder can be configured to select the encoding, quality and compression settings:

// Create MediaRecorder
recorder.setVideoSize(640, 480);
recorder.setVideoFrameRate(16); //might be auto-determined due to lighting
recorder.setVideoEncodingBitRate(3000000);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

You can also configure using preset qualities with CamcorderProfile:

CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);

See the available options here. You can also review this stackoverflow post for more details.

References

Finding these guides helpful?

We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.

Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.

Clone this wiki locally