apk下载视频录制apk下载,
项目源码地址为https://github.com/qdrzwd/VideoRecorder
补充:感谢雷军辉提供的文档
这里面有解决旋转办法,另外githup上面的源码已更新。
现在应该已经有很多人知道Vine和Instagram。前者做短视频分享起家后被Twitter收购,后者做照片分享起家后被Facebook收购,随后也迅速添加了视频分享功能。可以说短视频分享是社交网络适应移动互联网发展的大趋势。短视频分享应用已经如雨后春笋般崛起(算上最近新浪在推的“秒拍”,国内数得上名字的短视频分享已经有微视、秒拍、微可拍、玩拍,等等)。目前网上的录制视频的资料都是基于android自带的MediaRecorder类,但是这个类实在是个鸡肋,在实际项目中基本没什么用处。下面的项目中,录制视频使用javacv自带的api, 录制声音使用的是android的AudioRecord。
用过微视或vine的人都知道,他们的视频录制体验都是非常好的。微视虽然是模仿vine,
但是视频录制这一块我认为不比vine差。自己一直想做一个类似的视频录制app。
反编译微视和vine之后,发现微视使用的是自己编译的ffmpeg库,vine使用的是javacv库。
网上查资料后发现javacv已经提供了视频录制功能,并且包含有视频编辑等图像处理功能。
但是这之前从来没有听说过javacv,在上网查各种资料,纠结了几天之后,
偶然在githup上面发现了这个项目https://github.com/sourab-sharma/TouchToRecord。
本文以下视频录制功能,主要就是基于这个项目。在这里再次感谢原作者。
视频录制存在的问题
1.如何获取摄像头的数据
2.如何把获取到的数据保存到视频文件中
3.如何录制音频,并和视频合并
4.录制视频时如何实现暂停功能
5.android摄像头支持的分辨率可能不符合需求,需要转换分辨率
6.android手机录制出来的视频是旋转了90度的,如何实现旋转(转换到前置摄像头又如何处理)
先上几张最后的成果图
就单纯这几张图来看已经很像微视了,有木有,实现了断点录制视频、断点进度条、音视频混合、录制完成后分辨率为480*480。
但是还存在很多问题,视频旋转、利用图片合成视频、使用本地视频剪辑、后期视频特效添加等等。
下面开始代码展示了
首先需要javacv和javacpp的jar包,需要javacv需要的so库文件
这些都是必须的库文件,并且都可以在javacv开源项目中找到https://code.google.com/p/javacv/
直接上代码
首先是FFmpegFrameRecorder类,这个类是javacv包中就有的,已经实现了视频录制和音频录制,我们只是需要做一些修改
代码中已经写了比较详细的注释,就不再详细介绍了。
/*
* Copyright (C) 2009,2010,2011,2012,2013 Samuel Audet
*
* This file is part of JavaCV.
*
* JavaCV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version (subject to the "Classpath" exception
* as provided in the LICENSE.txt file that accompanied this code).
*
* JavaCV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JavaCV. If not, see <http://www.gnu.org/licenses/>.
*
*
* Based on the output-example.c file included in FFmpeg 0.6.5
* as well as on the decoding_encoding.c file included in FFmpeg 0.11.1,
* which are covered by the following copyright notice:
*
* Libavformat API example: Output a media file in any supported
* libavformat format. The default codecs are used.
*
* Copyright (c) 2001,2003 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.qd.recorder;
import com.googlecode.javacpp.BytePointer;
import com.googlecode.javacpp.DoublePointer;
import com.googlecode.javacpp.FloatPointer;
import com.googlecode.javacpp.IntPointer;
import com.googlecode.javacpp.Loader;
import com.googlecode.javacpp.Pointer;
import com.googlecode.javacpp.PointerPointer;
import com.googlecode.javacpp.ShortPointer;
import com.googlecode.javacv.FrameRecorder;
import java.io.File;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Map.Entry;
import static com.googlecode.javacv.cpp.avcodec.*;
import static com.googlecode.javacv.cpp.avformat.*;
import static com.googlecode.javacv.cpp.avutil.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.swresample.*;
import static com.googlecode.javacv.cpp.swscale.*;
/**
*
* @author Samuel Audet
*/
public class FFmpegFrameRecorder extends FrameRecorder {
public static FFmpegFrameRecorder createDefault(File f, int w, int h) throws Exception { return new FFmpegFrameRecorder(f, w, h); }
public static FFmpegFrameRecorder createDefault(String f, int w, int h) throws Exception { return new FFmpegFrameRecorder(f, w, h); }
private static Exception loadingException = null;
public static void tryLoad() throws Exception {
if (loadingException != null) {
throw loadingException;
} else {
try {
Loader.load(com.googlecode.javacv.cpp.avutil.class);
Loader.load(com.googlecode.javacv.cpp.avcodec.class);
Loader.load(com.googlecode.javacv.cpp.avformat.class);
Loader.load(com.googlecode.javacv.cpp.swscale.class);
} catch (Throwable t) {
if (t instanceof Exception) {
throw loadingException = (Exception)t;
} else {
throw loadingException = new Exception("Failed to load " + FFmpegFrameRecorder.class, t);
}
}
}
}
static {
/* initialize libavcodec, and register all codecs and formats */
av_register_all();
avformat_network_init();
}
public FFmpegFrameRecorder(File file, int audioChannels) {
this(file, 0, 0, audioChannels);
}
public FFmpegFrameRecorder(String filename, int audioChannels) {
this(filename, 0, 0, audioChannels);
}
public FFmpegFrameRecorder(File file, int imageWidth, int imageHeight) {
this(file, imageWidth, imageHeight, 0);
}
public FFmpegFrameRecorder(String filename, int imageWidth, int imageHeight) {
this(filename, imageWidth, imageHeight, 0);
}
public FFmpegFrameRecorder(File file, int imageWidth, int imageHeight, int audioChannels) {
this(file.getAbsolutePath(), imageWidth, imageHeight);
}
public FFmpegFrameRecorder(String filename, int imageWidth, int imageHeight, int audioChannels) {
this.filename = filename;
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
this.audioChannels = audioChannels;
this.pixelFormat = AV_PIX_FMT_NONE;
this.videoCodec = AV_CODEC_ID_NONE;
this.videoBitrate = 400000;
this.frameRate = 30;
this.sampleFormat = AV_SAMPLE_FMT_NONE;
this.audioCodec = AV_CODEC_ID_NONE;
this.audioBitrate = 64000;
this.sampleRate = 44100;
this.interleaved = true;
this.video_pkt = new AVPacket();
this.audio_pkt = new AVPacket();
}
public void release() throws Exception {
synchronized (com.googlecode.javacv.cpp.avcodec.class) {
releaseUnsafe();
}
}
public void releaseUnsafe() throws Exception {
/* close each codec */
if (video_c != null) {
avcodec_close(video_c);
video_c = null;
}
if (audio_c != null) {
avcodec_close(audio_c);
audio_c = null;
}
if (picture_buf != null) {
av_free(picture_buf);
picture_buf = null;
}
if (picture != null) {
avcodec_free_frame(picture);
picture = null;
}
if (tmp_picture != null) {
avcodec_free_frame(tmp_picture);
tmp_picture = null;
}
if (video_outbuf != null) {
av_free(video_outbuf);
video_outbuf = null;
}
if (frame != null) {
avcodec_free_frame(frame);
frame = null;
}
if (samples_out != null) {
for (int i = 0; i < samples_out.length; i++) {
av_free(samples_out[i].position(0));
}
samples_out = null;
}
if (audio_outbuf != null) {
av_free(audio_outbuf);
audio_outbuf = null;
}
video_st = null;
audio_st = null;
if (oc != null && !oc.isNull()) {
if ((oformat.flags() & AVFMT_NOFILE) == 0) {
/* close the output file */
avio_close(oc.pb());
}
/* free the streams */
int nb_streams = oc.nb_streams();
for(int i = 0; i < nb_streams; i++) {
av_free(oc.streams(i).codec());
av_free(oc.streams(i));
}
/* free the stream */
av_free(oc);
oc = null;
}
if (img_convert_ctx != null) {
sws_freeContext(img_convert_ctx);
img_convert_ctx = null;
}
if (samples_convert_ctx != null) {
swr_free(samples_convert_ctx);
samples_convert_ctx = null;
}
}
@Override protected void finalize() throws Throwable {
super.finalize();
release();
}
private String filename;
private AVFrame picture, tmp_picture;
private BytePointer picture_buf;
private BytePointer video_outbuf;
private int video_outbuf_size;
private AVFrame frame;
private Pointer[] samples_in;
private BytePointer[] samples_out;
private PointerPointer samples_in_ptr;
private PointerPointer samples_out_ptr;
private BytePointer audio_outbuf;
private int audio_outbuf_size;
private int audio_input_frame_size;
private AVOutputFormat oformat;
private AVFormatContext oc;
private AVCodec video_codec, audio_