You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AlarmRecorder.java 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package com.example.greenwatch.alarmrecorder;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.media.MediaCodec;
  5. import android.media.MediaExtractor;
  6. import android.media.MediaFormat;
  7. import android.media.MediaMuxer;
  8. import android.media.MediaRecorder;
  9. import android.os.Environment;
  10. import android.view.SurfaceHolder;
  11. import android.widget.Toast;
  12. import com.example.greenwatch.MainActivity;
  13. import com.example.greenwatch.alarmrecorder.runnables.AudioRecorder;
  14. import com.example.greenwatch.alarmrecorder.runnables.VideoRecorder;
  15. import com.example.greenwatch.sensors.AccelerometerSensor;
  16. import com.example.greenwatch.sensors.CameraSensor;
  17. import java.io.File;
  18. import java.io.IOException;
  19. import java.nio.ByteBuffer;
  20. public class AlarmRecorder {
  21. private static AlarmRecorder alarmRecorderInstance;
  22. private boolean isRecording;
  23. private String videoPath;
  24. private String audioPath;
  25. private MediaFormat videoFormat;
  26. private MediaFormat audioFormat;
  27. private MediaExtractor videoExtractor;
  28. private MediaExtractor audioExtractor;
  29. private AudioRecorder audioRecorderRunnable;
  30. private VideoRecorder videoRecorderRunnable;
  31. private SurfaceHolder previewHolder;
  32. private MediaRecorder videoRecorder;
  33. //private MediaRecorder audioRecorder;
  34. private Thread videoThread; // Video-Thread als Instanzvariable
  35. private Thread audioThread; // Audio-Thread als Instanzvariable
  36. private AlarmRecorder() {
  37. //audioRecorder = new MediaRecorder();
  38. //videoRecorder = new MediaRecorder();
  39. videoExtractor = new MediaExtractor();
  40. audioExtractor = new MediaExtractor();
  41. audioRecorderRunnable = new AudioRecorder();
  42. videoRecorderRunnable = new VideoRecorder();
  43. }
  44. public static synchronized AlarmRecorder getInstance() {
  45. if (alarmRecorderInstance == null){
  46. alarmRecorderInstance = new AlarmRecorder();
  47. }
  48. return alarmRecorderInstance;
  49. }
  50. public void setPreviewHolder(SurfaceHolder previewHolder) {
  51. this.previewHolder = previewHolder;
  52. }
  53. public void startRecording() {
  54. createStoragePaths(); //Speicherort und -namen für Audio- und Video-Datei
  55. setAudioPath(audioPath);
  56. setVideoPath(videoPath);
  57. setVideoRecorderPreviewHolder(previewHolder);
  58. //audioThread = new Thread(audioRecorderRunnable);
  59. videoThread = new Thread(videoRecorderRunnable);
  60. //Threads starten
  61. videoThread.start();
  62. //audioThread.start();
  63. }
  64. public void stopRecording(Context context) {
  65. try {
  66. //stopAudioRecording();
  67. stopVideoRecording();
  68. Toast.makeText(context, "Video- und Audioaufzeichnung beendet", Toast.LENGTH_SHORT).show();
  69. waitTillThreadsStopped();
  70. File videoFile = new File(videoPath); //Speichere das aufgenommene Video
  71. File audioFile = new File(audioPath); //Speichere die aufgenommene Audio
  72. if (videoFile.exists() && audioFile.exists()) {
  73. //Wenn Video- und Audioaufzeichnung gestoppt und abgespeichert sind, beginne mit dem Mergeprozess der beiden
  74. // mergeVideoWithAudio();
  75. Toast.makeText(context, "Video und Audio erfolgreich zusammengeführt", Toast.LENGTH_SHORT).show();
  76. } else {
  77. Toast.makeText(context, "Dateien wurden nicht gefunden!", Toast.LENGTH_SHORT).show();
  78. }
  79. } catch (RuntimeException stopException) {
  80. stopException.printStackTrace();
  81. }
  82. }
  83. private void createStoragePaths(){
  84. //Pfade zum Zwischenspeichern der aufgenommenen Audio und Video-Datei
  85. String externalStorageDirectory = Environment.getExternalStorageDirectory().getAbsolutePath();
  86. String dcimDirectory = externalStorageDirectory + "/DCIM";
  87. videoPath = dcimDirectory + "/video.mp4";
  88. audioPath = dcimDirectory + "/audio.mp3";
  89. }
  90. private void setVideoPath(String videoPath) {
  91. videoRecorderRunnable.setVideoPath(videoPath);
  92. }
  93. private void setVideoRecorderPreviewHolder(SurfaceHolder previewHolder) {
  94. videoRecorderRunnable.setPreviewHolder(previewHolder);
  95. }
  96. private void stopVideoRecording(){
  97. videoRecorderRunnable.stopVideoRecording();
  98. }
  99. private void setAudioPath(String audioPath) {
  100. audioRecorderRunnable.setAudioPath(audioPath);
  101. }
  102. private void stopAudioRecording(){
  103. audioRecorderRunnable.stopAudioRecording();
  104. }
  105. private void waitTillThreadsStopped(){
  106. try {
  107. videoThread.join();
  108. audioThread.join();
  109. } catch (InterruptedException e) {
  110. e.printStackTrace();
  111. }
  112. }
  113. private void mergeVideoWithAudio() {
  114. try {
  115. setVideoExtractorDataSource(); //extrahieren der Video Datei, die zuvor zwischengespeichert wurde
  116. setAudioExtractorDataSource(); //extrahieren der Audio Datei, die zuvor zwischengespeichert wurde
  117. //Speicherort der später zusammengeführten Datei
  118. String outputFilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getAbsolutePath() + "/merged_video.mp4";
  119. //MediaMuxer zum Zusammenführen einer Audio- und einer Videodatei
  120. MediaMuxer muxer = new MediaMuxer(outputFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
  121. int videoTrack = muxer.addTrack(videoFormat);
  122. int audioTrack = muxer.addTrack(audioFormat);
  123. muxer.start();
  124. ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
  125. MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
  126. videoExtraction(buffer, videoTrack, bufferInfo, muxer);
  127. audioExtraction(buffer, audioTrack, bufferInfo, muxer);
  128. muxer.stop();
  129. muxer.release();
  130. // Löschen der separaten Video- und Audio-Dateien
  131. deleteVideoFile();
  132. deleteAudioFile();
  133. } catch (IOException e) {
  134. e.printStackTrace();
  135. }
  136. }
  137. private void setVideoExtractorDataSource() {
  138. try {
  139. videoExtractor.setDataSource(videoPath);
  140. int videoTrackIndex = getTrackIndex(videoExtractor, "video/");
  141. if (videoTrackIndex < 0) {
  142. // Video-Track nicht gefunden
  143. return;
  144. }
  145. videoExtractor.selectTrack(videoTrackIndex);
  146. videoFormat = videoExtractor.getTrackFormat(videoTrackIndex);
  147. } catch (IOException e) {
  148. throw new RuntimeException(e);
  149. }
  150. }
  151. private void setAudioExtractorDataSource() {
  152. try {
  153. audioExtractor.setDataSource(audioPath);
  154. int audioTrackIndex = getTrackIndex(audioExtractor, "audio/");
  155. if (audioTrackIndex < 0) {
  156. // Audio-Track nicht gefunden
  157. return;
  158. }
  159. audioExtractor.selectTrack(audioTrackIndex);
  160. audioFormat = audioExtractor.getTrackFormat(audioTrackIndex);
  161. } catch (IOException e) {
  162. throw new RuntimeException(e);
  163. }
  164. }
  165. private int getTrackIndex(MediaExtractor extractor, String mimeType) {
  166. int trackCount = extractor.getTrackCount();
  167. for (int i = 0; i < trackCount; i++) {
  168. MediaFormat format = extractor.getTrackFormat(i);
  169. String trackMimeType = format.getString(MediaFormat.KEY_MIME);
  170. if (trackMimeType.startsWith(mimeType)) {
  171. return i;
  172. }
  173. }
  174. return -1;
  175. }
  176. private void videoExtraction(ByteBuffer buffer, int videoTrack, MediaCodec.BufferInfo bufferInfo, MediaMuxer muxer) {
  177. videoExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
  178. while (true) {
  179. int sampleSize = videoExtractor.readSampleData(buffer, 0);
  180. if (sampleSize < 0) {
  181. break;
  182. }
  183. long presentationTimeUs = videoExtractor.getSampleTime();
  184. bufferInfo.offset = 0;
  185. bufferInfo.size = sampleSize;
  186. bufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;
  187. bufferInfo.presentationTimeUs = presentationTimeUs;
  188. muxer.writeSampleData(videoTrack, buffer, bufferInfo);
  189. videoExtractor.advance();
  190. }
  191. }
  192. private void audioExtraction(ByteBuffer buffer, int audioTrack, MediaCodec.BufferInfo bufferInfo, MediaMuxer muxer) {
  193. audioExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
  194. while (true) {
  195. int sampleSize = audioExtractor.readSampleData(buffer, 0);
  196. if (sampleSize < 0) {
  197. break;
  198. }
  199. long presentationTimeUs = audioExtractor.getSampleTime();
  200. bufferInfo.offset = 0;
  201. bufferInfo.size = sampleSize;
  202. bufferInfo.flags = 0; // or MediaCodec.BUFFER_FLAG_KEY_FRAME
  203. bufferInfo.presentationTimeUs = presentationTimeUs;
  204. muxer.writeSampleData(audioTrack, buffer, bufferInfo);
  205. audioExtractor.advance();
  206. }
  207. }
  208. private void deleteVideoFile(){
  209. File videoFile = new File(videoPath);
  210. if (videoFile.exists()) {
  211. videoFile.delete();
  212. }
  213. }
  214. private void deleteAudioFile(){
  215. File audioFile = new File(audioPath);
  216. if (audioFile.exists()) {
  217. audioFile.delete();
  218. }
  219. }
  220. }