Exoplayer - Is it possible to check if a URL is a valid mp4/webm url before loading it?

1.4k Views Asked by At

Is it possible to check if it's actually a URL that can be loaded with the player before attempting to load it?

String mUrl = " --- ";
player = new SimpleExoPlayer.Builder(this).build();
       
        playerView.setPlayer(player);

        DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
                Util.getUserAgent(this, "yourApplicationName"));
        Uri uri = Uri.parse(mUrl);

        MediaSource videoSource =
                new ProgressiveMediaSource.Factory(dataSourceFactory)
                        .createMediaSource(uri);
        player.prepare(videoSource);

Or if theres a library that does this?

2

There are 2 best solutions below

0
On BEST ANSWER

One way to approach this would be to check the extension of the URL you are trying to load. For instance, the URL: http://thisisavideo/randompath/random_id.mp4 is most likely pointing to an mp4 resource. However, there are two main problems with this approach:

  1. You can't really bank on the URL-extension. http://simpleurlhaha.com could also be pointing to an mp4 resource.
  2. This approach does not guarantee that the URL is valid.



One approach that's guaranteed to work however, is to do an HTTP Head request on the URL and check the Content-Type. You can achieve this with Retrofit or any other Network Library you are using. If the URL is valid, you'll get a response similar to this:

HTTP/1.1 200 OK
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Accept-Ranges: bytes
Content-Length: 1034745
Content-Type: video/mp4
Date: Wed, 17 Sat 2020 13:01:19 GMT
Last-Modified: Fri, 8 Aug 2019 21:12:31 GMT
Server: Apache

As you can see, you can detect whether it's an MP4 or WebM URL by just doing an if-check on the Content-Type field.

Personally, I think the suggestion above is expensive because it involves making an additional network call and that adds to the overall processing time. If this still fits your use-case. Please, go ahead.

0
On

Why not just using Exoplayer?

    private void checkIfMediaValid(String url, MediaValidationCallback mediaValidationCallback){
        SimpleExoPlayer player = new SimpleExoPlayer.Builder(this).build();

        DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
                Util.getUserAgent(this, "yourApplicationName"));
        Uri uri = Uri.parse(url);

        MediaSource videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
                .createMediaSource(uri);
        player.prepare(videoSource);
        player.addListener(new Player.EventListener() {
            
            boolean listen = true;
            
            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                if(!listen)
                    return;
                if(playbackState== Player.STATE_IDLE){
                    ExoPlaybackException error = player.getPlaybackError();
                    if(error!=null){
                        if (error.type == ExoPlaybackException.TYPE_SOURCE) {
                            IOException cause = error.getSourceException();
                            if (cause instanceof HttpDataSource.HttpDataSourceException) {// An HTTP error occurred.
                                HttpDataSource.HttpDataSourceException httpError = (HttpDataSource.HttpDataSourceException) cause;
                                if (httpError instanceof HttpDataSource.InvalidResponseCodeException) {//RESPONSE CODE NOT 2XX
                                    callback(false);
                                } else {
                                    Throwable throwable = httpError.getCause();
                                    if(throwable instanceof UnknownHostException){//NO NETWORK
                                        //callback(false);
                                    }
                                }
                            }else if(cause instanceof FileDataSource.FileDataSourceException){//NOT FOUND (PROBABLY INVALID URL)
                                callback(false);
                            }else if(cause instanceof UnrecognizedInputFormatException){//WRONG INPUT(CONTENT)
                                callback(false);
                            }else if(cause instanceof Loader.UnexpectedLoaderException){
                                Throwable throwable = cause.getCause();
                                if(throwable instanceof SecurityException){//PROBABLY PERMISSION DENIED (Internet or ...)
                                    //callback(false);
                                }
                            }
                        }
                    }
                    if(listen){//NO CALLBACK
                        listen = false;
                        player.release();
                    }
                }else if(playbackState == Player.STATE_READY){
                    callback(true);
                }
            }

            private void callback(boolean result){
                mediaValidationCallback.result(result);
                listen = false;
                player.release();
            }
        });
    }

    interface MediaValidationCallback{
        void result(boolean isValid);
    }

then:

checkIfMediaValid(" --- ", isValid -> {
    //isValid : false
});