You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android平台如何将单张图片与视频合并生成MP4?求可用实现库

Hey there! Let’s figure out how to merge a single image with a video into an MP4 on Android—since you’ve already tried FFmpeg and OpenCV without luck, let’s dig into actionable fixes and alternative solutions.

1. Fixing Your FFmpeg Implementation (Most Reliable Path)

Chances are, the issue with FFmpeg wasn’t the library itself, but either the command parameters you used or a missing encoder in your build. Let’s use MobileFFmpeg—a pre-compiled, Android-friendly FFmpeg wrapper that includes all necessary codecs, so you don’t have to mess with native compilation.

Step 1: Add Dependency

Add this to your app-level build.gradle (Module level):

implementation 'com.arthenica:mobile-ffmpeg-full:4.4.LTS'

Step 2: Example Code for Merging Image + Video

Let’s say you want the image to play for 3 seconds at the start of the video, then transition to the original video. Here’s the code:

import com.arthenica.mobileffmpeg.FFmpeg;
import java.io.File;

// Define paths (replace with your actual file paths)
String imagePath = "/storage/emulated/0/Download/your_image.jpg";
String inputVideoPath = "/storage/emulated/0/Download/your_input.mp4";
String tempImageVideoPath = "/storage/emulated/0/Download/temp_image_video.mp4";
String outputPath = "/storage/emulated/0/Download/final_output.mp4";

// First, convert the image into a 3-second video clip
String[] imageToVideoCmd = new String[]{
    "-loop", "1",               // Loop the image to create a continuous video clip
    "-i", imagePath,            // Input image file path
    "-t", "3",                  // Duration of the image clip (3 seconds)
    "-c:v", "libx264",          // Use H.264 codec (universally compatible with MP4)
    "-r", "30",                 // Frame rate (match your input video for smooth transition)
    "-pix_fmt", "yuv420p",      // Critical pixel format for MP4 player compatibility
    "-c:a", "aac",              // Dummy audio codec (avoids errors even if image has no audio)
    "-strict", "experimental",
    "-shortest",
    tempImageVideoPath
};

// Execute the first command to generate the image clip
int result1 = FFmpeg.execute(imageToVideoCmd);
if (result1 == FFmpeg.RETURN_CODE_SUCCESS) {
    // Now concatenate the image clip and original video
    String[] concatCmd = new String[]{
        "-i", "concat:" + tempImageVideoPath + "|" + inputVideoPath,
        "-c", "copy",           // Copy codecs directly (fast, no re-encoding if formats match)
        outputPath
    };
    int result2 = FFmpeg.execute(concatCmd);
    if (result2 == FFmpeg.RETURN_CODE_SUCCESS) {
        // Clean up the temporary file if needed
        new File(tempImageVideoPath).delete();
    }
}

Key Fixes You Might Have Missed

  • Always use yuv420p pixel format—many media players won’t recognize MP4s with other formats.
  • Use the full variant of MobileFFmpeg to ensure all codecs (like libx264) are included.
  • Add proper storage permissions (Android 10+ requires using MediaStore or MANAGE_EXTERNAL_STORAGE for file access).
2. Native Android MediaCodec Approach (No Third-Party Libraries)

If you want to avoid FFmpeg entirely, you can use Android’s built-in MediaCodec and MediaMuxer APIs. This is more code-heavy but gives you full control over the process.

Core Idea

  1. Convert the image into a sequence of video frames (render the bitmap to a surface, then capture YUV frames).
  2. Write those frames to MediaMuxer for your desired duration (e.g., 3 seconds).
  3. Decode the original video’s frames and audio, then write them to the same MediaMuxer.

Sample Code Snippet (Simplified)

import android.media.MediaCodec;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.nio.ByteBuffer;

// Initialize MediaMuxer for MP4 output
MediaMuxer muxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

// Step 1: Write image frames to muxer
Bitmap imageBitmap = BitmapFactory.decodeFile(imagePath);
int width = imageBitmap.getWidth();
int height = imageBitmap.getHeight();

// Create a video track in the muxer
MediaFormat videoFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height);
videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, 1000000);
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
int videoTrackIndex = muxer.addTrack(videoFormat);

muxer.start();

// Write image frames for 3 seconds
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < 3000) {
    // Convert Bitmap to YUV buffer (use a helper function for this conversion)
    ByteBuffer yuvBuffer = convertBitmapToYUV(imageBitmap, width, height);
    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
    bufferInfo.offset = 0;
    bufferInfo.size = yuvBuffer.remaining();
    bufferInfo.presentationTimeUs = (System.currentTimeMillis() - startTime) * 1000;
    bufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;

    muxer.writeSampleData(videoTrackIndex, yuvBuffer, bufferInfo);
    // Sleep to maintain frame rate
    try {
        Thread.sleep(1000 / 30);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// Step 2: Write original video frames and audio (omitted for brevity)
// Use MediaExtractor to read the input video, decode frames with MediaCodec, then write to muxer

Note: You’ll need a helper function convertBitmapToYUV to convert the RGB bitmap to YUV 420 format—you can use RenderScript or manual pixel conversion for this.

3. Alternative Third-Party Libraries

If FFmpeg still isn’t working for you, try these options:

  • MP4Parser: A lightweight library for manipulating MP4 file structures. First, convert your image to a short MP4 clip (using MediaCodec), then use MP4Parser to concatenate it with your original video.
  • Glide + MediaMuxer: Use Glide to load and process the image, then render it as video frames to feed into MediaMuxer alongside the original video’s frames.
Troubleshooting Your Previous Attempts
  • FFmpeg Issues: If you were using a self-compiled FFmpeg build, you probably missed including codecs like libx264—MobileFFmpeg’s full variant fixes this. Also, double-check your command parameters for typos or missing flags (like -pix_fmt yuv420p).
  • OpenCV Issues: OpenCV’s VideoWriter can be finicky on Android. Make sure you’re using the correct four-character code for MP4 (CV_FOURCC('M','P','4','V')) and matching the input video’s resolution/frame rate. Also, ensure OpenCV is properly integrated with your Android project.

内容的提问来源于stack exchange,提问作者n00r_ay

火山引擎 最新活动