«

Android使用FFmpeg实现定时录像

时间:2024-3-2 17:31     作者:韩俊     分类: Android


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:12345@192.168.1.55 -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

标签: android

热门推荐