1. 程式人生 > >Android視訊錄製、播放的兩種方式

Android視訊錄製、播放的兩種方式

1、通過Intent的方式:Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

2、使用CameraAPI,呼叫MediaMediaRecorder

Intent的方式

注意:這裡播放camera錄製的視訊使用VideoView,不使用MediaPlayerSurfaceView的結合。用幀佈局Framelayout佈局,VideoViewImageView,播放時隱藏視訊縮圖,暫停時或初始化時顯示視訊縮圖。

因為VideoView沒有設定監聽播放和暫停狀態的事件,所以我自定義一個CustomVideoView繼承了

VideoView,在裡面建立一個監聽方法和重寫VideoView的播放、暫停的方法。

使用相機intent獲取視訊是使用最少程式碼使得你的應用獲取視訊的捷徑.一個視訊獲取intent可以包含以下額外資訊:

MediaStore.EXTRA_OUTPUT-此設定需要一個儲存視訊的路徑和檔名的Uri.此設定是可選的但是強列推薦的.如果你不指定此值,相機應用就把請求到的影象以預設的檔名儲存到預設的資料夾下,這些資訊儲存在返回的intentIntent.getData()欄位中.

MediaStore.EXTRA_VIDEO_QUALITY- 此值在最低質量最小檔案尺寸時是0,在最高質量最大檔案尺寸時是1

.

MediaStore.EXTRA_DURATION_LIMIT- 此值設定獲取視訊的長度,以秒為單位.

MediaStore.EXTRA_SIZE_LIMIT- 此值設定獲取視訊檔案的大小,以位元組為單位.

XML佈局檢視:


public class MainActivity extends AppCompatActivity {
    private static int REQUST_VIDEO = 1;
    private Button btn;
    private Button btn_start;
    private FrameLayout fl;
    private CustomVideoView video;
    private ImageView iv;
    private String sdCard;
    private String videoPath;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }
    private void init(){
        btn = ((Button) findViewById(R.id.btn_recoder));
        btn_start = ((Button) findViewById(R.id.btn_start));
        fl = ((FrameLayout) findViewById(R.id.fl_video));
        video = ((CustomVideoView) findViewById(R.id.video));
        iv = ((ImageView) findViewById(R.id.iv));
        sdCard = Environment.getExternalStorageDirectory().getPath();
        String currenTimeMillis = new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date(System.currentTimeMillis()));
        videoPath = sdCard + "/" +  "0000.mp4";
        MediaController controller = new MediaController(this);
        video.setMediaController(controller);
        if (video.isPlaying()){
            iv.setVisibility(View.INVISIBLE);
        }
        video.setPlayPauseListener(new CustomVideoView.PlayPauseListener() {
            @Override
            public void onPlay() {
                Toast.makeText(MainActivity.this,"播放",Toast.LENGTH_SHORT).show();
                iv.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onPause() {
                Toast.makeText(MainActivity.this,"暫停",Toast.LENGTH_SHORT).show();
                iv.setVisibility(View.VISIBLE);
            }
        });
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
                intent.putExtra(MediaStore.EXTRA_OUTPUT,videoPath);
                intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,1);
                startActivityForResult(intent,REQUST_VIDEO);
            }
        });
    }
    private Bitmap getVideoBitmap(String videoPath){
        MediaMetadataRetriever retriever = null;
        try {
            retriever = new MediaMetadataRetriever();
            retriever.setDataSource(videoPath);
            Bitmap bitmap = retriever.getFrameAtTime();
            return bitmap;
        }finally {
            retriever.release();
        }
    }
    private Bitmap getVideoBitmap2(Uri uri){
        MediaMetadataRetriever retriever = null;
        try {
            retriever = new MediaMetadataRetriever();
            retriever.setDataSource(this,uri);
            Bitmap bitmap = retriever.getFrameAtTime();
            return bitmap;
        }finally {
            retriever.release();
        }
    }
    public void start(View view){
        iv.setVisibility(View.INVISIBLE);
        video.start();
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK){
            if (requestCode == REQUST_VIDEO){
                fl.setVisibility(View.VISIBLE);
                btn_start.setVisibility(View.VISIBLE);
                Uri uri = data.getData();
                video.setVideoURI(uri);
//                Bitmap bitmap = getVideoBitmap(videoPath);
                Bitmap bitmap = getVideoBitmap2(uri);
                iv.setImageBitmap(bitmap);
            }
        }
    }
}

//自定義VideoView
public class CustomVideoView extends VideoView {
    private PlayPauseListener listener;
    public CustomVideoView(Context context) {
        super(context);
    }
    public CustomVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public CustomVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    public void setPlayPauseListener(PlayPauseListener listener){
        this.listener = listener;
    }
    @Override
    public void pause() {
        super.pause();
        if (listener!=null){
            listener.onPause();
        }
    }
    @Override
    public void start() {
        super.start();
        if (listener!=null){
            listener.onPlay();
        }
    }
    interface PlayPauseListener{
        void onPlay();
        void onPause();
    }
}

最終Intent方式的效果圖:


提取碼:yydc


許可權:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

例子中先用mediarecorder錄製儲存一個視訊然後播放看看效果,點選“跳轉”可以調到第二個Main2Activity中,用VideoView播放剛才錄製的視訊,Main2Activity主要測試如何播放在本地手機的視訊。

XML佈局:(MainActivity


程式碼:

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
    private static final String TAG = "MainActivity";
    private SurfaceView mSurfaceview;
    private Button btn_start_or_stop;
    private Button btn_play;
    private Button btn_turnto;
    private boolean isRecording = false;//是否正在錄影
    private boolean isPlay = false;//是否正在播放錄影
    private MediaRecorder mRecorder;
    private SurfaceHolder mSurfaceHolder;
    private ImageView mImageView;
    private Camera camera;
    private MediaPlayer mediaPlayer;
    private String path;
    private TextView time;
    private int text = 0;

    private Handler handler = new Handler();
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            text++;
            time.setText("錄製"+text+"秒");
            handler.postDelayed(this,1000);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        mSurfaceview = (SurfaceView) findViewById(R.id.surfaceview);
        mImageView = (ImageView) findViewById(R.id.imageview);
        btn_start_or_stop = (Button) findViewById(R.id.btn_start_or_stop);
        btn_turnto = (Button) findViewById(R.id.btn_turnto);
        btn_play = (Button) findViewById(R.id.btn_play);
        time = (TextView)findViewById(R.id.time);
        btn_turnto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (path != null){
                    File file = new File(path);
                    if(file.exists()){
                        Intent intent = new Intent(MainActivity.this,Main2Activity.class);
                        intent.putExtra("path",path);
                        startActivity(intent);
                    }else {
                        Toast.makeText(MainActivity.this,"視訊檔案不存在",Toast.LENGTH_SHORT).show();
                    }
                }else {
                    Toast.makeText(MainActivity.this,"檔案路徑不存在",Toast.LENGTH_SHORT).show();
                }
            }
        });
        btn_start_or_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isPlay){
                    if (mediaPlayer != null){
                        isPlay = false;
                        mediaPlayer.stop();
                        mediaPlayer.reset();
                        mediaPlayer.release();
                        mediaPlayer = null;
                    }
                }
                if (!isRecording){
                    handler.postDelayed(runnable,1000);
                    mImageView.setVisibility(View.GONE);
                    if (mRecorder == null){
                        mRecorder = new MediaRecorder();// 建立mediarecorder物件
                        text = 0;//當點選停止之後,每一次進到這裡都要重置錄製的時間數
                    }
                    camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                    if (camera != null){
                        camera.setDisplayOrientation(90);//攝像圖旋轉90度
                        camera.unlock();
                        mRecorder.setCamera(camera);// 設定錄製視訊源為Camera(相機)
                    }
                    try{
                        mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); // 這兩項需要放在setOutputFormat之前
                        mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 這兩項需要放在setOutputFormat之前
                        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//設定錄製視訊的輸出格式
                        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//設定音訊編碼格式
                        mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);//設定視訊編碼格式// 設定錄製的視訊編碼h263 h264
                        mRecorder.setVideoSize(640,480);//設定視訊的解析度,必須放在設定編碼和格式的後面,否則報錯
                        mRecorder.setVideoFrameRate(30);//這是設定視訊錄製的幀率,即1秒鐘30幀。。必須放在設定編碼和格式的後面,否則報錯
                        mRecorder.setVideoEncodingBitRate(4 * 1024 * 1024);//這個屬性很重要,這個也直接影響到視訊錄製的大小,這個設定的越大,視訊越清晰
                        mRecorder.setOrientationHint(90);//視訊旋轉90度
                        mRecorder.setMaxDuration(30 * 1000);//設定錄製最長時間為30秒
                        mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());//設定錄製視訊時的預覽畫面
                        path = getSdPath();
                        if (path != null){
                            File dir = new File(path + "/recordtest");
                            if (!dir.exists()){
                                dir.mkdir();
                            }
                            path = dir + "/" + getDate() + ".mp4";
                            mRecorder.setOutputFile(path);// 設定視訊檔案輸出的路徑
                            mRecorder.prepare();// 準備錄製
                            mRecorder.start();// 開始錄製
                            isRecording = true;
                            btn_start_or_stop.setText("停止");
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }else {
                    if (isRecording){
                        try {
                            handler.removeCallbacks(runnable);
                            mRecorder.stop();// 停止錄製
                            mRecorder.reset();// 恢復到未初始化的狀態
                            mRecorder.release();// 釋放資源
                            mRecorder = null;
                            btn_start_or_stop.setText("開始");
                            if (camera != null){
                                camera.release();
                                camera = null;
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                        isRecording = false;
                    }
                }
            }
        });
        btn_play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                isPlay = true;
                mImageView.setVisibility(View.GONE);
                if (mediaPlayer == null){
                    mediaPlayer = new MediaPlayer();
                }
                mediaPlayer.reset();
                Uri uri = Uri.parse(path);
                if (uri == null){
                    Toast.makeText(MainActivity.this,"請先錄製視訊",Toast.LENGTH_SHORT).show();
                    return;
                }
                mediaPlayer = MediaPlayer.create(MainActivity.this,uri);//使用mediaplayer播放uri視訊
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);//設定播放流媒體型別。
                mediaPlayer.setDisplay(mSurfaceHolder);// 設定螢幕
                try{
                    mediaPlayer.prepare();
                }catch (Exception e){
                    e.printStackTrace();
                }
                mediaPlayer.start();
            }
        });
        SurfaceHolder holder = mSurfaceview.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (!isRecording){
            mImageView.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mSurfaceHolder = holder;
    }
    /**
     * 獲取系統時間
     *
     * @return
     */
    private static String getDate(){
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DATE);
        int minute = calendar.get(Calendar.MINUTE);
        int hour = calendar.get(Calendar.HOUR);
        int second = calendar.get(Calendar.SECOND);
        String date = "" + year + (month + 1) + day + hour + minute + second;
        return date;
    }
    /**
     * 獲取SD path
     *
     * @return
     */
    public String getSdPath(){
        File sdDir = null;
        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);//判斷sd卡是否存在
        if (sdCardExist){
            sdDir = Environment.getExternalStorageDirectory();//獲取根目錄
            return sdDir.toString();
        }
        return null;
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // 將holder,這個holder為開始在onCreate裡面取得的holder,將它賦給mSurfaceHolder
        mSurfaceHolder = holder;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // surfaceDestroyed的時候同時物件設定為null
        mSurfaceview = null;
        mSurfaceHolder = null;
        handler.removeCallbacks(runnable);
        if (mRecorder != null) {
            mRecorder.release();
            mRecorder = null;
        }
        if (camera != null) {
            camera.release();
            camera = null;
        }
        if (mediaPlayer != null){
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}

效果圖:


MAin2Activity

XML佈局(MAin2Activity

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="project.wgc.mymediarecordertest01.Main2Activity">
    <VideoView
        android:id="@+id/video"
        android:layout_width="300dp"
        android:layout_height="400dp"
        />
    <Button
        android:id="@+id/btn_play"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="播放"/>
</LinearLayout>

Main2Activity程式碼:

public class Main2Activity extends AppCompatActivity {
    private Button play;
    private VideoView video;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        video = ((VideoView) findViewById(R.id.video));
        Intent intent = getIntent();
        String path = intent.getStringExtra("path");
        //Uri uri = Uri.parse(path);//第一種。把路徑轉換為uri,然後給videoview設定,
//        video.setVideoURI(uri);
        video.setVideoPath(path);//第二種,直接把本地視訊的路徑設定給VideoView也可以.
        play = ((Button) findViewById(R.id.btn_play));
        play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                video.start();
            }
        });
    }
}

效果圖:


提取碼:z3ul