bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.42k stars 1.57k forks source link

Same input m4a audio file get different output mp3 file #2073

Open Mhuang77 opened 11 months ago

Mhuang77 commented 11 months ago

lib version:

    implementation 'org.bytedeco:openblas:0.3.23-1.5.9:linux-x86_64'
    implementation 'org.bytedeco:opencv:4.7.0-1.5.9:linux-x86_64'
    implementation 'org.bytedeco:ffmpeg:6.0-1.5.9:linux-x86_64'
    implementation 'org.bytedeco:javacpp:1.5.9:linux-x86_64'
    implementation 'org.bytedeco:javacv:1.5.9'

jdk version

openjdk version "11.0.19" 2023-04-18

os version

Ubuntu 22.04.1 LTS

reproduce this issue: test m4a file: input_case.zip

test code:

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;

import java.io.*;

public class TestMain {
    final static String INPUT_FILE_NAME = "/tmp/input.m4a";
    final static String OUTPUT_FILE_PATH = "/tmp/";

    public static void main(String[] args) throws IOException {
        // test1 use the filename as the FFmpegFrameRecorder's constructor parameter 
        test1();
        // test2 use the FileOutputStream as the FFmpegFrameRecorder's constructor parameter
        test2();
        // test3 use the ByteArrayOutputStream as the FFmpegFrameRecorder's constructor parameter and write the ByteArrayOutputStream to the file
        test3();
    }

    private static void extracted(FFmpegFrameGrabber grabber, FFmpegFrameRecorder recorder) throws FFmpegFrameRecorder.Exception, FrameGrabber.Exception {
        recorder.setFormat("MP3");
        recorder.start();
        grabber.start();
        Frame frame;
        while ((frame = grabber.grabFrame()) != null) {
            recorder.record(frame);
        }
    }

    public static void test1() throws FileNotFoundException, FFmpegFrameRecorder.Exception, FrameGrabber.Exception {
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(new File(INPUT_FILE_NAME));
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(OUTPUT_FILE_PATH + "test1.mp3", 1);
        extracted(grabber, recorder);
        grabber.stop();
        recorder.stop();
    }

    public static void test2() throws FFmpegFrameRecorder.Exception, FrameGrabber.Exception, FileNotFoundException {
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(new File(INPUT_FILE_NAME));
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new FileOutputStream(OUTPUT_FILE_PATH + "test2.mp3"), 1);
        extracted(grabber, recorder);
        grabber.stop();
        recorder.stop();
    }

    public static void test3() throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(new File(INPUT_FILE_NAME));
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(baos, 1);
        extracted(grabber, recorder);
        byte[] mp3bytes = baos.toByteArray();
        FileOutputStream fileOutputStream = new FileOutputStream(OUTPUT_FILE_PATH + "test3.mp3");
        fileOutputStream.write(mp3bytes);
        grabber.stop();
        recorder.stop();
        fileOutputStream.close();
    }
}

get different mp3 files

md5sum test1.mp3 test2.mp3 test3.mp3

c20347a0b1d1bc5335ef7e74c2b833c2  test1.mp3
98bba388491102a5d2d3a5a8e55f20df  test2.mp3
753e39024eefc131dba501367ae1cd2f  test3.mp3
saudet commented 11 months ago

I think that's normal, but someone would need to look into this.

Mhuang77 commented 11 months ago

I think that's normal, but someone would need to look into this.

Why is this considered a normal phenomenon?

saudet commented 11 months ago

It's probably caused by encoding with multiple threads which are not finely synchronized for efficiency, but causes this.