Reputation: 473
I am creating a mobile application that does the following
The sequence has been perfectly implemented on iOS.
On Android however, I can record the video, save the video, upload the video, but cannot stream (progressive download) the file from Azure using VideoView and MediaController.
I get the "Can't play this video"
The video I uploaded from the Android app does work on iOS and HTML5 and pretty much any other media player.
If I choose to play the *.mp4 I saved locally (before uploading the *.mp4) through VideoView, it works fine. So at this stage, before uploading to Azure, the video seems in a working condition.
Another test I did, was to upload Big Buck Bunny, through Azure Storage Explorer, and that seems to work perfectly.
So I suspect I am might be missing a header when I upload the file to Azure or incorrect encoding for streaming.
Here is my code, nothing extraordinary:
MediaRecorder Settings to display and record the video:
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setOutputFile(getVideoFile(activity).getAbsolutePath());
mediaRecorder.setVideoEncodingBitRate(1000000);
mediaRecorder.setVideoFrameRate(5);
mediaRecorder.setVideoSize(videoSize.getWidth(), videoSize.getHeight());
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
Upload the file by using CloudBlockBlob:
StorageCredentials credentials = new StorageCredentialsSharedAccessSignature(sasQueryString);
URI containerUri = new URI(blobUri);
CloudBlockBlob blob = new CloudBlockBlob(URI.create(blobUri), credentials);
blob.getProperties().setContentType("video/mp4");
blob.uploadFromFile(imageUri);
Trying to play the uploaded file:
videoView = (VideoView) findViewById(R.id.videoView);
MediaController mediaController = new MediaController(this);
videoView.setVideoURI(Uri.parse("http://xox.blob.core.windows.net/container/movie.mp4"));
videoView.setMediaController(mediaController);
videoView.start();
At which point I get "Can't play this video"!
As I said to start off with, this uploaded file works seemingly on every other media player including iOS and HTML5. And if I play the locally saved version of the file on Android, it works.
But I can't play the file on Android from Azure after uploaded. Nor can I play the file created and uploaded by iOS created on Android.
Is it encoding the issue? Am I uploading the blob incorrectly? What makes Android's ViewVideo stricter on which video's it will play as oppose to other media players
Upvotes: 2
Views: 2006
Reputation: 26
I was facing the same problem, so I created a method to create to get the video:
public static byte[] getVideo(String videoName) {
try {
// Get a reference to the blob
CloudBlockBlob blob = container.getBlockBlobReference(videoName);
// Check if the blob exists
if (!blob.exists()) {
System.out.println("Blob video does not exist: " + videoName);
return null; // Return null if the blob does not exist
}
URI blobUri = blob.getUri();
System.out.println("Azure Blob URL video: " + blobUri);
// Create a ByteArrayOutputStream to store the video data
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// Download the blob's content to the ByteArrayOutputStream
blob.download(outputStream);
// Close the ByteArrayOutputStream
outputStream.close();
// Return the video data as a byte array
return outputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Then in my Fragment:
byte[] videoData = azureManager.getVideo("azureVideoName");
try {
// Create a temporary file to store the video
File tempFile = File.createTempFile(videoName, ".mp4", getContext().getCacheDir());
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(videoData);
fos.close();
videoView.requestFocus();
// Set the video URI to the local temporary file
videoView.setVideoURI(Uri.fromFile(tempFile));
// Start the video playback
videoView.start();
} catch (IOException e) {
e.printStackTrace();
}
Upvotes: 0
Reputation: 429
@Peter's answer should work. just instead of MediaPlayer.prepare() call MediaPlayer.prepareAsync() after setting Prepared listener.
And while recording in ios if you are simply changing extension of video from .mov to .mp4 then most of android device will not play it. also verify that in a MP4 container video stream should be encoded using H264 codec and audio with AAC codec.
Upvotes: 0
Reputation: 85
Try using this Library: https://github.com/brianwernick/ExoMedia
It encapsulate ExoPlayer api similar to VideoView's API.
Also, facing issue while trying to play recorder and converted with FFMPEG videos from Azure Blob Storage.
Upvotes: 1
Reputation: 27944
You probably calling the start() to early, start the video when the mediaplayer is ready to start playing: Reference MediaPlayer
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
videoView.start();
}
});
Upvotes: 1