私のアプリケーションでは、デバイスからビデオを録画し、同時にサーバーに投稿する必要があります (5 秒ごと)。このために、私は Http サービスを使用しています (ここでは RTSP を使用したくありません)。録画と同時に投稿できます。
ただし、サーバー側のファイルは再生できません (VLC でも)。両方のファイルのサイズはバイト単位で同じです (サーバー ファイルとデバイス ファイル)。問題がサーバーまたは私の側にあることを確認するためのテスト目的で、サーバー投稿コードにコメントし、SDカードの別のファイルにデータを書き込みました(5秒ごとに記録しながら同時に)が、そのファイルも同じサイズで再生できませんデバイスまたは VLC で。
package com.techgene.instantrecorder;
import java.io.File;
import java.io.IOException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.media.MediaRecorder.OnInfoListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
import android.widget.VideoView;
import com.techgene.instantrecorder.utility.Util;
public class SafeVideoRecorder extends Activity implements SurfaceHolder.Callback
{
public static final String EXTRA_USE_FRONT_FACING_CAMERA ="frontcamera";
private static final String ROOT_DIR = Environment.getExternalStorageDirectory().toString() + "/InstantRecorder";
private static final int DUAL_MODE = 1;
private static final int MONO_MODE = 2;
private int currentMode;
private static final String TAG = "VideoRecorder";
public static Boolean mRecording = false;
private Boolean mUseFrontFacingCamera = false, isFromCall = false;
private VideoView mVideoView = null;
private MediaRecorder mVideoRecorder = null;
private Camera mCamera;
private String uniqueOutFile;
private ProgressDialog progress;
private Button btnStop, btnStartRecord, btnDual, btnMono;
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_video_recorder);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mVideoView = (VideoView) this.findViewById(R.id.videoView);
btnStop = (Button) findViewById(R.id.btnStop);
btnStop.setVisibility(View.GONE);
btnStop.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
try
{
stopRecording();
if(progress != null && progress.isShowing())
progress.dismiss();
progress = ProgressDialog.show(SafeVideoRecorder.this, "", "Uploading...");
new Thread(new Runnable()
{
@Override
public void run()
{
// Util util = new Util();
// final int respCode = util.upLoad2Server(uniqueOutFile);
//
// if(currentMode == MONO_MODE)
// {
// File file = new File(uniqueOutFile);
// if(file.exists())
// file.delete();
// }
runOnUiThread(new Runnable()
{
@Override
public void run()
{
if(progress != null && progress.isShowing())
progress.dismiss();
// if(respCode == 200)
// {
// Toast.makeText(SafeVideoRecorder.this, "Successfully uploaded to server", Toast.LENGTH_SHORT).show();
// }
// else
// {
// Toast.makeText(SafeVideoRecorder.this, "Unable to upload server", Toast.LENGTH_SHORT).show();
// }
try {
configureCameraRecorder(mVideoView.getHolder());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
btnStop.setVisibility(View.GONE);
btnStartRecord.setVisibility(View.VISIBLE);
btnDual.setVisibility(View.GONE);
btnMono.setVisibility(View.GONE);
}
});
}
}).start();
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
});
btnStartRecord = (Button) findViewById(R.id.btnStartRecord);
btnStartRecord.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
btnDual.setVisibility(View.VISIBLE);
btnMono.setVisibility(View.VISIBLE);
btnStop.setVisibility(View.GONE);
btnStartRecord.setVisibility(View.GONE);
startRecord();
}
});
btnDual = (Button) findViewById(R.id.btnDual);
btnDual.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
currentMode = DUAL_MODE;
isFromCall = true;
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"+"9703033575"));
startActivityForResult(intent, 1010);
btnDual.setVisibility(View.GONE);
btnMono.setVisibility(View.GONE);
btnStartRecord.setVisibility(View.GONE);
btnStop.setVisibility(View.VISIBLE);
}
});
btnMono = (Button) findViewById(R.id.btnMono);
btnMono.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
currentMode = MONO_MODE;
btnDual.setVisibility(View.GONE);
btnMono.setVisibility(View.GONE);
btnStartRecord.setVisibility(View.GONE);
btnStop.setVisibility(View.VISIBLE);
}
});
//mUseFrontFacingCamera = getIntent().getExtras().getBoolean(EXTRA_USE_FRONT_FACING_CAMERA, false);
if(mUseFrontFacingCamera)
{
// If caller wants to use front facing camera, then make sure the device has one...
// Hard coded to only open front facing camera on Xoom (model MZ604)
// For more universal solution try:
// http://stackoverflow.com/questions/2779002/how-to-open-front-camera-on-android-platform
String deviceModel = android.os.Build.MODEL;
if (deviceModel.contains("MZ604"))
{
mUseFrontFacingCamera = true;
}
else
{
Toast.makeText(getApplicationContext(), "The App isn't designed to use this Android's front facing camera.\n " +
"The device model is : " + deviceModel, Toast.LENGTH_LONG).show();
mUseFrontFacingCamera = false;
}
}
final SurfaceHolder holder = mVideoView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@SuppressLint("NewApi") @Override
public void surfaceCreated(SurfaceHolder holder)
{
Log.e(TAG, "surfaceCreated()");
try
{
if(!isFromCall)
{
Log.e(TAG, "configureCameraRecorder");
configureCameraRecorder(holder);
startRecord();
}
else
{
Log.e(TAG, "configureCamera ONLY");
if (mCamera != null)
{
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if (mUseFrontFacingCamera)
{
//hard coded assuming 1 is the front facing camera
mCamera = Camera.open(1);
}
else
{
mCamera = Camera.open();
}
// Camera setup is based on the API Camera Preview demo
mCamera.setPreviewDisplay(holder);
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(640, 480);
mCamera.setParameters(parameters);
mCamera.startPreview();
mCamera.unlock();
mVideoRecorder.setCamera(mCamera);
mVideoRecorder.setPreviewDisplay(holder.getSurface());
}
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
private void startRecord()
{
try
{
File file = new File(ROOT_DIR);
if(!file.exists())
file.mkdir();
uniqueOutFile = ROOT_DIR + "/IR_" + System.currentTimeMillis() + ".mp4";
File outFile = new File(uniqueOutFile);
if (outFile.exists())
{
outFile.delete();
}
if(mVideoRecorder != null)
{
Log.e(TAG, "Recording started");
mVideoRecorder.setOutputFile(uniqueOutFile);
mVideoRecorder.prepare();
mVideoRecorder.start();
mRecording = true;
new Thread(new Runnable()
{
@Override
public void run()
{
Util util = new Util();
final int respCode = util.upLoad2Server(uniqueOutFile);
}
}).start();
}
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Log.v(TAG, "Width x Height = " + width + "x" + height);
}
private void stopRecording() throws Exception
{
Log.e(TAG, "stopRecording()");
mRecording = false;
if (mVideoRecorder != null)
{
mVideoRecorder.stop();
mVideoRecorder.release();
mVideoRecorder = null;
}
if (mCamera != null)
{
mCamera.reconnect();
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
@Override
protected void onDestroy()
{
try
{
stopRecording();
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
super.onDestroy();
}
@SuppressLint("NewApi")
private void configureCameraRecorder(SurfaceHolder holder) throws Exception
{
if (mVideoRecorder != null)
{
mVideoRecorder.stop();
mVideoRecorder.release();
mVideoRecorder = null;
}
if (mCamera != null)
{
mCamera.reconnect();
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
try
{
if (mUseFrontFacingCamera)
{
//hard coded assuming 1 is the front facing camera
mCamera = Camera.open(1);
}
else
{
mCamera = Camera.open();
}
// Camera setup is based on the API Camera Preview demo
mCamera.setPreviewDisplay(holder);
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(640, 480);
mCamera.setParameters(parameters);
mCamera.startPreview();
mCamera.unlock();
mVideoRecorder = new MediaRecorder();
mVideoRecorder.setCamera(mCamera);
mVideoRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mVideoRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mVideoRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// THREE_GPP
mVideoRecorder.setVideoSize(640, 480);// YouTube recommended size: 320x240, OpenGazer eye tracker: 640x480 YouTube HD: 1280x720
mVideoRecorder.setVideoFrameRate(20); //might be auto-determined due to lighting
mVideoRecorder.setVideoEncodingBitRate(3000000);// 3 megapixel, or the max of the camera
mVideoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP
int sdk = android.os.Build.VERSION.SDK_INT;
// Gingerbread and up can have wide band ie 16,000 hz recordings
// (Okay quality for human voice)
if (sdk >= 10)
{
mVideoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
mVideoRecorder.setAudioSamplingRate(16000);
}
else
{
// Other devices only have narrow band, ie 8,000 hz
// (Same quality as a phone call, not really good quality for any purpose.
// For human voice 8,000 hz means /f/ and /th/ are indistinguishable)
mVideoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
}
// mVideoRecorder.setMaxDuration(30000); // limit to 30 seconds
mVideoRecorder.setOnInfoListener(new OnInfoListener()
{
@Override
public void onInfo(MediaRecorder mr, int what, int extra)
{
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED)
{
try
{
Log.e(TAG, "MEDIA_RECORDER_INFO_MAX_DURATION_REACHED reached");
stopRecording();
if(progress != null && progress.isShowing())
progress.dismiss();
progress = ProgressDialog.show(SafeVideoRecorder.this, "", "Uploading...");
new Thread(new Runnable()
{
@Override
public void run()
{
Util util = new Util();
final int respCode = util.upLoad2Server(uniqueOutFile);
runOnUiThread(new Runnable()
{
@Override
public void run()
{
if(progress != null && progress.isShowing())
progress.dismiss();
if(respCode == 200)
{
Toast.makeText(SafeVideoRecorder.this, "Successfully uploaded to server", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(SafeVideoRecorder.this, "Unable to upload server", Toast.LENGTH_SHORT).show();
}
}
});
}
}).start();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
});
mVideoRecorder.setPreviewDisplay(holder.getSurface());
}
catch (Exception e)
{
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
@Override
protected void onPause()
{
super.onPause();
if (mCamera != null)
{
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
Log.e(TAG, "onActivityResult()");
// if(requestCode == 1010 && resultCode == RESULT_OK)
// {
//
// }
isFromCall = true;
}
}
package com.techgene.instantrecorder.utility;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import android.util.Log;
import com.techgene.instantrecorder.Appconstants;
import com.techgene.instantrecorder.SafeVideoRecorder;
import com.techgene.instantrecorder.VideoRecorder;
public class Util
{
public int upLoad2Server(String sourceFileUri)
{
int serverResponseCode = 0;
// String upLoadServerUri = "http://113.193.181.52:90/test/videos/add-video1.php";
String upLoadServerUri = "http://113.193.181.52:90/test/videos/add-video1.php?name=sample&description=Sample video&lat="
+ Appconstants.DEVICE_LAT
+ "&lng="
+ Appconstants.DEVICE_LANG;
upLoadServerUri = upLoadServerUri.replace(" ", "%20");
Log.e("Util", "Url: "+upLoadServerUri);
HttpURLConnection conn = null;
DataOutputStream dos = null;
int bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
File sourceFile = new File(sourceFileUri);
if (!sourceFile.isFile())
{
Log.e("Util", "Source File Does not exist");
return 0;
}
try
{
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(upLoadServerUri);
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
// conn.setRequestProperty("Content-Type", "multipart/form-data;");
// conn.setRequestProperty("uploaded_file", fileName);
// FileOutputStream fos = new FileOutputStream("/mnt/sdcard/hi.mp4");
dos = new DataOutputStream(conn.getOutputStream());
// dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""+fileName);
bytesAvailable = fileInputStream.available();
buffer = new byte[maxBufferSize];
while (SafeVideoRecorder.mRecording || (!SafeVideoRecorder.mRecording && bytesAvailable > 0))
{
Log.e("Util", "available : " + bytesAvailable);
bufferSize = Math.min(bytesAvailable, maxBufferSize);
fileInputStream.read(buffer, 0, bufferSize);
dos.write(buffer, 0, bufferSize);
dos.flush();
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
while (bytesAvailable <= 0 && SafeVideoRecorder.mRecording)
{
Log.e("Util", "NOT available : " + bytesAvailable);
Thread.sleep(5000);
bytesAvailable = fileInputStream.available();
}
}
// Responses from the server (code and message)
serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn.getResponseMessage();
Log.i("Util", "Upload file to server, HTTP Response is : " + serverResponseMessage + ": " + serverResponseCode);
fileInputStream.close();
dos.flush();
dos.close();
}
catch (Exception e)
{
e.printStackTrace();
}
// this block will give the response of upload link
try
{
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null)
{
Log.i("Util", "RES Message: " + line);
}
rd.close();
}
catch (Exception ioex)
{
Log.e("Util", "error: " + ioex.getMessage(), ioex);
}
return serverResponseCode;
}
}