You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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_ENCODER parameter. Always validate the codec post-recording as a fallback.
  • Codec Labels: H.264 is often represented by the string avc1 in metadata, but some devices might use slightly different labels—adjust your check if needed.
  • File Persistence: The file created with File.createTempFile will 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 17:03:01