com.googlecode.mp4parser对于mp3音频文件失败了吗?

时间:2017-06-20 09:36:58

标签: android audio mp4parser

我正在使用com.googlecode.mp4parser库来合并音频文件。我有一个外部音频mp3文件,我存储在raw资源中。由于以下异常,此文件无法合并,以下是我的代码:

从原始文件夹中读取文件:

InputStream is = context.getResources().openRawResource(R.raw.my_mp3_file);
        OutputStream output = null;
        try {
            File file = new File(context.getFilesDir(), "silence.mp3");
            if(!file.exists()) {
                file.createNewFile();
            }
            output = new FileOutputStream(file);
            byte[] buffer = new byte[4 * 1024]; // or other buffer size
            int read;

            while ((read = is.read(buffer)) != -1) {
                output.write(buffer, 0, read);
            }
            output.flush();
            output.close();
            fileReference= file;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace(); // handle exception, define IOException and others
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

读取电影的代码(失败):

if(fileReference.exists()) {
                    Movie m = new MovieCreator().build(fileReference.getAbsolutePath());
                }

获取此Movie m代码失败时抛出异常:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.coremedia.iso.boxes.MovieBox.getBoxes(java.lang.Class)' on a null object reference

它适用于某些mp3文件失败的原始资源文件?这里有什么问题?

2 个答案:

答案 0 :(得分:0)

经过大量研究后,这是我的结论和解决方案 用于合并音频和视频的MP4Parser仅使用.m4a扩展名

String root = Environment.getExternalStorageDirectory().toString();
            String audio = root + "/" + "tests.m4a";
            String video = root + "/" + "output.mp4";
            String output = root + "/" + "aud_vid.mp4";
            mux(video, audio, output);

这是方法

public boolean mux(String videoFile, String audioFile, String outputFile) {
    Movie video;
    try {
        video = new MovieCreator().build(videoFile);
    } catch (RuntimeException e) {
        e.printStackTrace();
        return false;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }

    Movie audio;
    try {
        audio = new MovieCreator().build(audioFile);
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    } catch (NullPointerException e) {
        e.printStackTrace();
        return false;
    }

    Track audioTrack = audio.getTracks().get(0);
    video.addTrack(audioTrack);

    Container out = new DefaultMp4Builder().build(video);

    FileOutputStream fos;
    try {
        fos = new FileOutputStream(outputFile);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        return false;
    }
    BufferedWritableFileByteChannel byteBufferByteChannel = new BufferedWritableFileByteChannel(fos);
    try {
        out.writeContainer(byteBufferByteChannel);
        byteBufferByteChannel.close();
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

private static class BufferedWritableFileByteChannel implements WritableByteChannel {
    private static final int BUFFER_CAPACITY = 1000000;

    private boolean isOpen = true;
    private final OutputStream outputStream;
    private final ByteBuffer byteBuffer;
    private final byte[] rawBuffer = new byte[BUFFER_CAPACITY];

    private BufferedWritableFileByteChannel(OutputStream outputStream) {
        this.outputStream = outputStream;
        this.byteBuffer = ByteBuffer.wrap(rawBuffer);
    }

    @Override
    public int write(ByteBuffer inputBuffer) throws IOException {
        int inputBytes = inputBuffer.remaining();

        if (inputBytes > byteBuffer.remaining()) {
            dumpToFile();
            byteBuffer.clear();

            if (inputBytes > byteBuffer.remaining()) {
                throw new BufferOverflowException();
            }
        }

        byteBuffer.put(inputBuffer);

        return inputBytes;
    }

    @Override
    public boolean isOpen() {
        return isOpen;
    }

    @Override
    public void close() throws IOException {
        dumpToFile();
        isOpen = false;
    }

    private void dumpToFile() {
        try {
            outputStream.write(rawBuffer, 0, byteBuffer.position());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

答案 1 :(得分:0)

Seem like this issue happens because Google devs have forgotten to handle that NullPointerException case. After several hours diving into the code base, I finally found the solution and It works very fine, you can try this:

         Movie movie;         
         try{
            movie = MovieCreator.build(videoPath);
         }catch(NullPointerException e){
             Log.d("AsyncTask", "Catch null getMovieBoxes");
             FileDataSourceImpl fileDataSource = new FileDataSourceImpl(new File(videoPath));
             IsoFile isoFile = new IsoFile(fileDataSource);
             List<TrackBox> trackBoxes = isoFile.getBoxes(TrackBox.class);
             for (TrackBox trackBox : trackBoxes) {
                  SchemeTypeBox schm = Path.getPath(trackBox, "mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schm[0]");
                  if (schm != null && (schm.getSchemeType().equals("cenc") || schm.getSchemeType().equals("cbc1"))) {
                                movie.addTrack(new CencMp4TrackImplImpl(fileDataSource.toString() + "[" + trackBox.getTrackHeaderBox().getTrackId() + "]", trackBox));
                  } else {
                  movie.addTrack(new Mp4TrackImpl(fileDataSource.toString() + "[" + trackBox.getTrackHeaderBox().getTrackId() + "]" , trackBox));
                  }
              }

         }