Android使用FFmpeg实现定时录像

1、需求分析

在Android下实现定时的录像,首先可以在网络摄像机设置页面实现,在某个时刻录像,但是这种情况福想的视频不是保持在摄像机本地就是上传到摄像机厂家提供的服务器上并不是适应所有的需求。

其次,可以在Android下借助FFmpeg实现保存摄像机的视频流,对于定时功能可以在Android程序中实现。

2、具体实现

(1)定时

定时录像则需要在每一天的某个时刻或者某些时刻进行录像,这样可一借助Android的闹钟机制实现。

Android的闹钟实现上基于AlarmManager这个类的,其中有两个主要的方法:

AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE);

    public void set(int type, long triggerAtMillis, PendingIntent operation) {
         try {
             manager.set(type, triggerAtMillis, operation);
             } catch (RemoteException ex) {
             }
    }               
<span style="font-family:FangSong_GB2312;font-size:14px;">       public void setRepeating(int type, long triggerAtMillis,
               long intervalMillis, PendingIntent operation) {
           try {
               manager.setRepeating(type, triggerAtMillis, intervalMillis, operation);
          } catch (RemoteException ex) {
          }
    }                                                                               </span>

第一个方法是简单的注册一个闹铃,第二个方法是设置重复闹铃,就是隔一段时间响一次。

这里使用第二种方法,其具体实现为:

<span style="white-space:pre">		</span>Intent intent = new Intent(AlarmSetingActivity.this, AlarmReceiver.class);
		PendingIntent sender = PendingIntent.getBroadcast(AlarmSetingActivity.this, 0, intent, 0);

	            long firstTime = SystemClock.elapsedRealtime();	// 开机之后到现在的运行时间(包括睡眠时间)
	            long systemTime = System.currentTimeMillis();

	            <span style="white-space:pre">		</span>Calendar calendar = Calendar.getInstance();
			 	calendar.setTimeInMillis(System.currentTimeMillis());
			 	calendar.setTimeZone(TimeZone.getTimeZone("GMT+8")); // 这里时区需要设置一下,不然会有8个小时的时间差
			 	calendar.set(Calendar.MINUTE, mMinute);
			 	calendar.set(Calendar.HOUR_OF_DAY, mHour);
			 	calendar.set(Calendar.SECOND, 0);
			 	calendar.set(Calendar.MILLISECOND, 0);

			 	// 选择的每天定时时间
			 	long selectTime = calendar.getTimeInMillis();	

			 	// 如果当前时间大于设置的时间,那么就从第二天的设定时间开始
			 	if(systemTime > selectTime) {
			 	    Toast.makeText(AlarmSetingActivity.this, "设置的时间小于当前时间", Toast.LENGTH_SHORT).show();
			 	    calendar.add(Calendar.DAY_OF_MONTH, 1);
			            selectTime = calendar.getTimeInMillis();
			 	}

			 	// 计算现在时间到设定时间的时间差
			 	long time = selectTime - systemTime;
		 		firstTime += time;

	            // 进行闹铃注册
	            AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE);
	            manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
	                            firstTime, 6*60*60*1000, sender);

	            Log.i(TAG, "time ==== " + time + ", selectTime ===== "
            			+ selectTime + ", systemTime ==== " + systemTime + ", firstTime === " + firstTime);

	            Toast.makeText(AlarmSetingActivity.this, "设置定时成功! ", Toast.LENGTH_LONG).show();

解释下setRepeat的第一个参数:

AlarmManager.RTC,硬件闹钟,不唤醒手机(也可能是其它设备)休眠;当手机休眠时不发射闹钟。

AlarmManager.RTC_WAKEUP,硬件闹钟,当闹钟发躰时唤醒手机休眠;

AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒手机休眠;当手机休眠时不发射闹钟。

AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,当闹钟发躰时唤醒手机休眠;

RTC闹钟和ELAPSED_REALTIME最大的差别就是前者可以通过修改手机时间触发闹钟事件,后者要通过真实时间的流逝,即使在休眠状态,时间也会被计算

闹铃注册完了之后发送广播,我们还要接受广播:

<span style="white-space: pre;">	</span>public class AlarmReceiver extends BroadcastReceiver {
	<span style="white-space: pre;">	</span>@Override
	<span style="white-space: pre;">	</span>public void onReceive(Context context, Intent intent) {
	<span style="white-space: pre;">	</span>Toast.makeText(context, "~~开始录制视频~~", Toast.LENGTH_LONG).show();
		new MyThread().start();
	}
	class MyThread extends Thread {
		public void run() {
			try {
				@SuppressWarnings("unused")
				Process proc = Runtime.getRuntime().exec(
						"su  -c ./data/misc/command_record.sh");
			<span style="white-space: pre;">	</span>} catch (IOException e) {
				<span style="white-space: pre;">	</span>// TODO Auto-generated catch block
				<span style="white-space: pre;">	</span>e.printStackTrace();
			<span style="white-space: pre;">	</span>}
		<span style="white-space: pre;">	</span>}
	<span style="white-space: pre;">	</span>}

 <span style="white-space: pre;">	</span>}

还需要在AndroidManifest.xml注册:

<span style="white-space: pre;">	</span><receiver
            android:name="com.wr.alarmrecord.AlarmReceiver"
            android:process=":remote" >
        </receiver>

android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。

(2)录像

录像的实现是在android下调用FFmpeg执行命令行命令实现的,思路是:

定时启动后,每隔一段时间调用脚本执行录像命令,将录像保存到SD卡下,但是由于SD卡容量有限,所以当保存的数目到达一定量时就删除文件,录像的命名是以摄像机名字加上日期而成的。脚本如下:

<span style="white-space:pre">	</span>#!/system/bin/sh

<span style="white-space:pre">	</span>file=".count.rec"
<span style="white-space:pre">	</span>count=0
<span style="white-space:pre">	</span>da=`date "+%Y-%m-%d-%H-%M-%S"`
<span style="white-space:pre">	</span>camera="海康威视"

<span style="white-space:pre">	</span>if [ -f $file ]; then
    <span style="white-space:pre">	</span>    read count < $file
        fi

<span style="white-space:pre">	</span>if [ $(($count + 1)) -ne 40 ]

<span style="white-space:pre">	</span>then
   <span style="white-space:pre">	</span>    echo $(($count + 1))
            echo $(($count + 1)) > $file

<span style="white-space:pre">	</span>else
	    echo $(($count + 1))
            echo 0 > $file

	    cd /mnt/sdcard/
	    rm -r admin/

<span style="white-space:pre">	</span>fi
            cd /data/misc/ffmpeg/
            ./ffmpeg -y -i rtsp://admin:[email protected] -vcodec copy -acodec copy -t 0:1:0 -f flv /mnt/sdcard/admin/$camera-$da.flv

3、截图

4、源码下载:

http://download.csdn.net/detail/xdwyyan/8691263

5、参考

http://jakend.iteye.com/blog/1980842

http://blog.csdn.net/liuhaomatou/article/details/22445755

时间: 2024-08-30 14:20:23

Android使用FFmpeg实现定时录像的相关文章

[原]如何在Android用FFmpeg+SDL2.0解码图像线程

关于如何在Android上用FFmpeg+SDL2.0解码显示图像参考[原]如何在Android用FFmpeg+SDL2.0解码显示图像 ,关于如何在Android使用FFmpeg+SDL2.0解码声音参考[原]如何在Android用FFmpeg+SDL2.0解码声音.但是该文章有一个问题,就是解码出来的声音有很大的噪音,基本无法听清,这是由于对于声音的处理有问题.故本文参考ffmpeg-sdl音频播放分析声音解码的处理,解码出来的声音就正常了. 博主的开发环境:Ubuntu 14.04 64位

Android学习笔记(不定时更新)

在很久之前,我就想写写博客,不过本人比较懒,这几天心血来潮,决定开写博客,因为学习,实习,面试关系,不会定时更新,以下是我所学的知识,总结分享一下,如有不正确,希望各位轻喷. QQ:545662362.欢迎交流,因为第一次写博客,格式什么的也不是特别好.好了,学习目录如下 1.Android 开发环境搭建 2.Android 应用程序 3.Android 常用基本控件 4.Android 常用高级控件 5.Android 消息与广播 6.Service 后台服务 7.Android 数据存储与服

[原]如何在Android用FFmpeg解码图像

前一篇[原]如何用Android NDK编译FFmpeg 我们知道了如何使用NDK来编译Android平台下使用的FFmpeg动态库.这篇文章我们就可以使用Android下的JNI来调用FFMpeg进行解码了. 一.编译出来可以使用的动态库,我们会看到如下输出则表示link完成了: CC libavcodec/log2_tab.o CC libavutil/log2_tab.o CC libswresample/log2_tab.o AR libavcodec/libavcodec.a LD l

android 移植ffmpeg后so库的使用

今天折腾了一天,可算是有所收获,成功的用jni调用了libffmpeg中的一个方法-----avcodec_version(),至于avcodec_version()是干什么用的我不大清楚,应该是获取版本信息吧,没有深入的去研究ffmpeg. 这里主要是想把折腾一天所获取的经验记录下来,以免时间长全忘了,也希望能给其他人一点借鉴,不至于和我一样一点头绪都没有连猜带蒙的,本文纯属个人心得,高手可以无视.... 要在android上用ffmpeg首先得奖ffmpeg工程移植到android上,这里就

Android时钟应用的定时框架分析

Android系统闹钟定时功能框架,总体来说就是用数据库存储定时数据,有一个状态管理器来统一管理这些定时状态的触发和更新.在Andriod系统中实现定时功能,最终还是要用到系统提供的AlarmManager,只是当一个定时完成后怎么继续处理,或者中间怎么更新定时的时间或者状态,像闹钟这种应用程序,每天重复定时,或者一周选择其中的几天,闹钟响了延迟5分钟再次响铃,这时候就需要想一种好的办法来让管理这些数据和状态,下面就分析一下Android系统闹钟的实现. 1.基本结构 Alarm 代表一条定时数

FFmpeg截图和录像

使用FFmpeg可将一段视频流中截取图像和录制一段时长的视频: 1.截图命令 ./ffmpeg -i rtsp://admin:[email protected] -s 368x208 -y -f image2 /mnt/sdcard/images1.png 2.录像(1分钟) ./ffmpeg -y -i rtsp://admin:[email protected] -vcodec copy -acodec copy -t 0:1:0 -f flv /mnt/sdcard/myvideo.fl

关于Android中的PollingService定时轮询任务的讲解

1.创建PollingThread类,在log打印出“New message!” class PollingThread extends Thread { @Override public void run() { Log.i("zzf", "Polling..."); } } 2.创建PollingReceiver,用于接收Service传递信息并重新执行PollingService public class PollingReceiver extends Bro

Android使用FFMpeg实现推送视频直播流到服务器

背景 在过去的2015年中,视频直播页的新宠无疑是户外直播.随着4G网络的普及和覆盖率的提升,主播可以在户外通过手机进行直播.而观众也愿意为这种可以足不出户而观天下事的服务买单.基于这样的背景,本文主要实现在Android设备上采集视频并推流到服务器. 概览 如下图所示,在安卓上采集并推流主要应用到两个类.首先是安卓Api自带的Camera,实现从摄像头采集图像.然后是Javacv 中的FFMpegFrameRecorder类实现对Camera采集到的帧编码并推流. 关键步骤与代码 下面结合上面

Android 中使用MediaRecorder进行录像详解(视频录制)

在这里给出自己的一个测试DEMO,里面注释很详细.简单的视频录制功能. package com.video; import java.io.IOException; import android.app.Activity; import android.content.pm.ActivityInfo; import android.graphics.PixelFormat; import android.media.MediaRecorder; import android.os.Bundle;