Android中如何为MediaStore.ACTION_VIDEO_CAPTURE设置H.264编码?
Got it, I totally get why you want to stick with the system's video capture UI—it's clean, users know how to use it, and you don't have to build everything from scratch. Let's tackle your two main questions: setting H.264 encoding for MediaStore.ACTION_VIDEO_CAPTURE, and verifying the codec used after recording.
1. Specify H.264 Encoding and MP4 Format in the Intent
While not all device manufacturers honor every extra parameter for the system capture intent, there are standard extras you can add to hint that you want H.264-encoded MP4. To make this more reliable, we'll also specify an output file path (so we control the format directly) and use FileProvider to handle Android's security rules for file URIs.
Here's the modified code:
private Uri savedVideoUri; // Store this to reference later in onActivityResult private void launchSystemVideoCapture() { File videoFile = null; try { // Create a unique MP4 filename String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String videoFileName = "VID_" + timeStamp; File storageDir = getExternalFilesDir(Environment.DIRECTORY_MOVIES); // Create temp MP4 file videoFile = File.createTempFile(videoFileName, ".mp4", storageDir); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "Failed to create video file", Toast.LENGTH_SHORT).show(); return; } if (videoFile != null) { // Get a secure URI for the file using FileProvider savedVideoUri = FileProvider.getUriForFile( this, "com.your.package.name.fileprovider", // Replace with your app's FileProvider authority videoFile ); Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); // Request H.264 video encoder takeVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_ENCODER, MediaRecorder.VideoEncoder.H264); // Request MP4 output format takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT_FORMAT, MediaRecorder.OutputFormat.MPEG_4); // Set the output URI to our MP4 file takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, savedVideoUri); // Optional: Set high video quality (0 = low, 1 = high) takeVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); if (takeVideoIntent.resolveActivity(getPackageManager()) != null) { startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE); } } }
Don't Forget FileProvider Setup (Android 7.0+)
To use FileProvider, add this to your AndroidManifest.xml:
<application> <!-- ... other app components ... --> <provider android:name="androidx.core.content.FileProvider" android:authorities="com.your.package.name.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application>
Then create res/xml/file_paths.xml to define where the provider can access files:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="movies" path="Movies/" /> </paths>
2. Verify the Video Codec After Recording
Since some devices might ignore the intent extras, you need to validate the actual codec of the recorded video. Use MediaMetadataRetriever to extract this info in onActivityResult:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) { Uri videoUri = null; // If we set EXTRA_OUTPUT, data.getData() might be null—use our saved URI instead if (data != null && data.getData() != null) { videoUri = data.getData(); } else { videoUri = savedVideoUri; } MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(this, videoUri); // Extract codec info (H.264 is usually labeled as "avc1") String videoCodec = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_CODEC); String mimeType = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE); Log.d("VideoCheck", "Codec: " + videoCodec + ", MIME: " + mimeType); // Validate if it's H.264/MP4 if (videoCodec != null && videoCodec.contains("avc1") && "video/mp4".equals(mimeType)) { // Success! Proceed to upload to server uploadVideoToServer(videoUri); } else { // Notify user to re-record if codec doesn't match Toast.makeText(this, "Recorded video isn't H.264 MP4. Please try again.", Toast.LENGTH_LONG).show(); } } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, "Failed to check video codec", Toast.LENGTH_SHORT).show(); } finally { retriever.release(); } } }
Key Notes
- Compatibility: Not all system camera apps respect the
EXTRA_VIDEO_ENCODERparameter. Always validate the codec post-recording as a fallback. - Codec Labels: H.264 is often represented by the string
avc1in metadata, but some devices might use slightly different labels—adjust your check if needed. - File Persistence: The file created with
File.createTempFilewill stay in your app's external files directory until you delete it, so remember to clean up old videos if needed.
内容的提问来源于stack exchange,提问作者Iter Ator

