使用Android MediaRecorder(API级别<24)进行暂停和恢复录制功能。

9

在使用 MediaRecorder 时,在API级别低于24的情况下,我们没有暂停/恢复的功能。

因此有一种方法可以实现:

  1. 在暂停事件中停止录制并创建记录文件。
  2. 在恢复事件中再次开始录制并创建另一个文件,然后不断重复此过程,直到用户按下停止键。
  3. 最后合并所有文件。

许多人在SO上问过这个问题,但是找不到解决方法。人们谈论通过在暂停操作上停止录制并在恢复时重新启动来创建多个媒体文件。因此我的问题是:如何以编程方式合并/连接所有媒体文件?

注意:在我的情况下,MPEG4容器-M4a用于音频,MP4用于视频。

我尝试使用 SequenceInputStream 将各自生成的记录文件的多个InputStream合并。但它总是只返回第一个文件。

代码片段:

Enumeration<InputStream> enu = Collections.enumeration(inputStreams);
        SequenceInputStream sqStream = new SequenceInputStream(enu);
        while ((oneByte = sqStream.read(buffer)) != -1) {
            fileOutputStream.write(buffer, 0, oneByte);

        }
        sqStream.close();
        while (enu.hasMoreElements()) {
            InputStream element = enu.nextElement();
            element.close();
        }
        fileOutputStream.flush();
        fileOutputStream.close();

可能是在Android中暂停和恢复音频录制的重复问题。 - soshial
2个回答

17

我可以使用mp4parser库来解决这个问题。非常感谢这个库的作者:)

在您的gradle文件中添加以下依赖项:

compile 'com.googlecode.mp4parser:isoparser:1.0.2'
解决方案是在用户暂停时停止记录,并在恢复时重新开始,如在stackoverflow的许多其他答案中已经提到的一样。将生成的所有音频/视频文件存储在数组中,并使用下面的方法合并所有媒体文件。示例也采用了mp4parser库,并根据我的需要进行了一些修改。
停止录制器并在恢复时重新开始以解决问题,如stackoverflow中其他答案所述。将所有生成的音频/视频文件保存在数组中,并使用以下方法合并所有媒体文件。此示例也来自mp4parser库,但我根据自己的需要稍作修改。
public static boolean mergeMediaFiles(boolean isAudio, String sourceFiles[], String targetFile) {
        try {
            String mediaKey = isAudio ? "soun" : "vide";
            List<Movie> listMovies = new ArrayList<>();
            for (String filename : sourceFiles) {
                listMovies.add(MovieCreator.build(filename));
            }
            List<Track> listTracks = new LinkedList<>();
            for (Movie movie : listMovies) {
                for (Track track : movie.getTracks()) {
                    if (track.getHandler().equals(mediaKey)) {
                        listTracks.add(track);
                    }
                }
            }
            Movie outputMovie = new Movie();
            if (!listTracks.isEmpty()) {
                outputMovie.addTrack(new AppendTrack(listTracks.toArray(new Track[listTracks.size()])));
            }
            Container container = new DefaultMp4Builder().build(outputMovie);
            FileChannel fileChannel = new RandomAccessFile(String.format(targetFile), "rw").getChannel();
            container.writeContainer(fileChannel);
            fileChannel.close();
            return true;
        }
        catch (IOException e) {
            Log.e(LOG_TAG, "Error merging media files. exception: "+e.getMessage());
            return false;
        }
    }

将isAudio标志设置为true以处理音频文件,设置为false以处理视频文件。


0

另一个解决方案是与FFmpeg合并

将此行添加到您的应用程序build.gradle

implementation 'com.writingminds:FFmpegAndroid:0.3.2'

使用以下代码合并视频。

String textFile = "";
try {
    textFile = getTextFile().getAbsolutePath();
} catch (IOException e) {
    e.printStackTrace();
}
String[] cmd = new String[]{
        "-y",
        "-f",
        "concat",
        "-safe",
        "0",
        "-i",
        textFile,
        "-c",
        "copy",
        "-preset",
        "ultrafast",
        getVideoFilePath()};

mergeVideos(cmd);

getTextFile()

 private File getTextFile() throws IOException {
        videoFiles = new String[]{firstPath, secondPath, thirdPatch};
        File file = new File(getActivity().getExternalFilesDir(null), System.currentTimeMillis() + "inputFiles.txt");
        FileOutputStream out = new FileOutputStream(file, false);
        PrintWriter writer = new PrintWriter(out);
        StringBuilder builder = new StringBuilder();
        for (String path : videoFiles) {
            if (path != null) {
            builder.append("file ");
            builder.append("\'");
            builder.append(path);
            builder.append("\'\n");
            }
        }
        builder.deleteCharAt(builder.length() - 1);
        String text = builder.toString();
        writer.print(text);
        writer.close();
        out.close();
        return file;
    }

getVideoFilePath()

 private String getVideoFilePath() {
        final File dir = getActivity().getExternalFilesDir(null);
        return (dir == null ? "" : (dir.getAbsolutePath() + "/"))
                + System.currentTimeMillis() + ".mp4";
    }

合并视频()

private void mergeVideos(String[] cmd) {
        FFmpeg ffmpeg = FFmpeg.getInstance(getActivity());
        try {
            ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {

                @Override
                public void onStart() {
                    startTime = System.currentTimeMillis();
                }

                @Override
                public void onProgress(String message) {

                }

                @Override
                public void onFailure(String message) {
                    Toast.makeText(getActivity(), "Failed " + message, Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onSuccess(String message) {

                }

                @Override
                public void onFinish() {
                    Toast.makeText(getActivity(), "Videos are merged", Toast.LENGTH_SHORT).show();
                }
            });
        } catch (FFmpegCommandAlreadyRunningException e) {
            // Handle if FFmpeg is already running
        }
    }

在合并之前运行这段代码
private void checkFfmpegSupport() {
        FFmpeg ffmpeg = FFmpeg.getInstance(this);
        try {
            ffmpeg.loadBinary(new LoadBinaryResponseHandler() {

                @Override
                public void onStart() {

                }

                @Override
                public void onFailure() {
                    Toast.makeText(VouchActivity.this, "FFmpeg not supported on this device :(", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onSuccess() {

                }

                @Override
                public void onFinish() {

                }
            });
        } catch (FFmpegNotSupportedException e) {
            // Handle if FFmpeg is not supported by device
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接