Video inkl. Overlays aufnehmen?

  • Antworten:5
Jochen K.
  • Forum-Beiträge: 33

23.08.2012, 20:09:39 via Website

Hi zusammen!

Ich stehe vor einem scheinbar fast unlösbaren Problem!

Folgendes: Ich habe eine Beta App erstellt, in der ich Videos aufnehmen kann. Über dem Video Preview liegen zwei Buttons und später sollen auch GPS Daten dort dargestellt werden. Das Ganze sollte soweit kein Thema sein.

Nun möchte ich aber die GPS Daten direkt mit auf dem Video aufnehmen!!! Da ich mir nicht vorstellen kann, dass ich diese in das Video rendern kann, bin ich auf die Idee gekommen, ein Video vom Display zu erstellen. Also ich starte die Video Preview und nehme aber nicht über die CameraLinse auf, sondern den Bildschirm. Das scheint aber nicht wirklich zu funktionieren! Dann habe ich mir überlegt, ich nehme einfach eine Serie von Screenshot vom Display auf, aber da musste ich feststellen, dass der (Gerade nur ein Screenshot, noch keine Serie) die Video Vorschau nicht mit aufnimmt. Vor allem stellt ich mir dann noch die Frage, wie ich später aus den Images ein Video generieren kann. Man bedenke: Ich möchte keinerlei Tools verwenden also PC, Mac oder ähnliches. Es geht hier wirklich darum, ein Video , in dem auch direkt andere Elemente die über dem Preview liegen, aufzunehmen.

Mein letzter Versuch war es wie gesagt, einzelne Screenshot aufzunehmen und diese dann später irgendwie in ein Video umzusetzen.

Mein Code der letzten Beta App:

1package com.example.androidvideofromphotos;
2
3import java.io.File;
4import java.io.FileOutputStream;
5import java.io.IOException;
6
7import android.app.Activity;
8import android.graphics.Bitmap;
9import android.graphics.PixelFormat;
10import android.hardware.Camera;
11import android.os.Bundle;
12import android.os.Environment;
13import android.view.SurfaceHolder;
14import android.view.SurfaceView;
15import android.view.View;
16import android.view.View.OnClickListener;
17import android.widget.Button;
18import android.widget.RelativeLayout;
19
20public class MainActivity extends Activity implements OnClickListener, SurfaceHolder.Callback {
21
22 private Button startBtn, stopBtn, openCamera;;
23 private Camera camera;
24 private SurfaceView surfaceView;
25 private SurfaceHolder surfaceHolder;
26 boolean previewing = false;
27 private RelativeLayout view;
28
29 @Override
30 public void onCreate(Bundle savedInstanceState) {
31 super.onCreate(savedInstanceState);
32 setContentView(R.layout.main);
33
34 startBtn = (Button) findViewById(R.id.start);
35 stopBtn = (Button) findViewById(R.id.stop);
36 openCamera = (Button) findViewById(R.id.open);
37
38 startBtn.setOnClickListener(this);
39 stopBtn.setOnClickListener(this);
40 openCamera.setOnClickListener(this);
41
42
43 getWindow().setFormat(PixelFormat.UNKNOWN);
44 surfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
45 surfaceHolder = surfaceView.getHolder();
46 surfaceHolder.addCallback(this);
47 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
48
49
50
51 }
52
53
54
55 @Override
56 public void onClick(View v) {
57 long clickedElement = v.getId();
58
59
60
61 if(clickedElement == R.id.start){
62 File root = Environment.getExternalStorageDirectory();
63 File file = new File(root,"myImage.jpg");
64 SurfaceView mainLayout = (SurfaceView) findViewById(R.id.surfaceView1);
65
66 View v1=mainLayout.getRootView();
67 v1.setDrawingCacheEnabled(true);
68 Bitmap bm=v1.getDrawingCache();
69
70 if(bm!=null){
71 System.out.println("Nicht leer");
72 FileOutputStream fos = null;
73
74 try {
75 fos = new FileOutputStream(file);
76 if(fos != null){
77 bm.compress(Bitmap.CompressFormat.JPEG, 100, fos);
78 fos.close();
79 }
80 } catch (Exception e) {
81 e.printStackTrace();
82 }
83 }
84
85 /* RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.rootlayout);
86 //SurfaceView mainLayout = (SurfaceView) findViewById(R.id.surfaceView1);
87 File root = Environment.getExternalStorageDirectory();
88 File file = new File(root,"androidlife.jpg");
89 Bitmap b = Bitmap.createBitmap(mainLayout.getWidth(), mainLayout
90 .getHeight(), Bitmap.Config.ARGB_8888);
91 Canvas c = new Canvas(b);
92 mainLayout.draw(c);
93 FileOutputStream fos = null;
94 try {
95 fos = new FileOutputStream(file);
96
97 if (fos != null) {
98 b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
99 fos.close();
100 }
101 } catch (Exception e) {
102 e.printStackTrace();
103 }*/
104
105
106 }
107 else if(clickedElement == R.id.stop){
108
109 }
110 else if(clickedElement == R.id.open){
111 camera = Camera.open();
112
113 try {
114 camera.setPreviewDisplay(surfaceHolder);
115 } catch (IOException e) {
116 // TODO Auto-generated catch block
117 e.printStackTrace();
118 }
119 camera.setDisplayOrientation(90);
120 camera.startPreview();
121 }
122
123 }
124
125
126
127 @Override
128 public void surfaceChanged(SurfaceHolder holder, int format, int width,
129 int height) {
130 // TODO Auto-generated method stub
131
132 }
133
134
135
136 @Override
137 public void surfaceCreated(SurfaceHolder holder) {
138 // TODO Auto-generated method stub
139
140 }
141
142
143
144 @Override
145 public void surfaceDestroyed(SurfaceHolder holder) {
146 // TODO Auto-generated method stub
147
148 }
149
150
151}

Hat jemand eine Idee, wie ich das noch umsetzen könnte? Ich hoffe ihr könnt mir weiter helfen...wenn ich Google noch weiter befrage, dann werde ich wohl als Stalker eingestuft :D -

Danke und Grüße

Antworten
Ultimate Software
  • Forum-Beiträge: 110

23.08.2012, 22:15:26 via Website

Nur zum Mut machen: Es muss gehen. ;-)

Denn ich habe ein Tool das am PC den Handy-Inhalt wiedergibt (und aufzeichnet, aber am PC), das überträgt auch die Video-Anzeige. Nur leider hilft dir das beim "Wie" auch nicht weiter ;-)

<td class="alt1"> <!-- google_ad_section_start -->Mehrere WLANs?? Versuch doch mal den <a href="http://goo.gl/7ojEp&quot; target="_blank">SSID Selector</a>: <img src="images/smilies/extra/thumbsup.gif" border="0" alt="" title="Thumbsup" class="inlineimg" /><!-- google_ad_section_end --> </td>

Antworten
Jochen K.
  • Forum-Beiträge: 33

24.08.2012, 00:17:57 via Website

Nabend,

ja ich weiss. Tools gibt es einige. Die Frage ist nur, ob es auch direkt auf dem Android geht?! Das Aufnehmen direkt über die Kamera bringt mich ja nicht weiter. Ich müsste ja wie schon gesagt das Display des Handys aufnehmen. Aber nirgends was gefunden in Bezug auf Video aufnahmen des Displays. Immer nur Bilder. Und auch da wie schon oben erwähnt das Problem, dass ich nur ein schwarzes Bild bekomme was er mir speichert, obwohl die Kamera Vorschau aktiv ist...

Ich habe nun schon des öfteren ffmpeg gelesen, aber habe noch keine Ahnung, was genau das sein soll. Wenn ich wirklich eine Serie von Bildern aufnehmen könnte, die das Display abfotografiert und somit auch die Kamera Vorschau inklusive der GPS Daten, wäre ich schon einen Schritt weiter.

Bei der Suche danach, bin ich auf das hier gestoßen (mindestens 200 mal :D ) : http://www.youtube.com/watch?v=kVlEydQ_3Cw

Das ist schon recht cool...ich dachte erst, dass die ein Video aufnehmen, aber da scheint es auch eine Serie von Bildern zu sein, die dann in ein Video umgesetzt werden direkt auf dem Android...

Wenn noch jemand was weiss, BITTE melden!!!! Bekomme bald Meldung von Google, dass ungewöhnlich viele Anfragen gestellt wurden und ich bestätigen muss, dass ich ein Mensch bin :D

Danke und Grüße aus dem Münsterland

Antworten
Jochen K.
  • Forum-Beiträge: 33

24.08.2012, 04:21:17 via Website

Guten Morgen alle zusammen!

Es ist 04:12 und ich bin endlich ein kleines Stückchen weiter...

Also, ich habe folgendes gemacht: Wenn ich in der App nun ein Photo machen will, dann mache ich eines von der Camera und zusätzlich einen Screenshot. Diese beiden Bitmaps setze ich dann mittels Canvas zusammen, nachdem ich bei dem Screenshot den schwarzen Hintergrund auf Transparent gesetzt habe. Das funktioniert ansich ganz gut, aaaber: Anfangs habe ich immer eine Fehlermeldung: OutOfMemoryError bekommen -> HASS!

Also habe ich folgendes gemacht: in der onPictureTaken habe ich erst eine Bitmap aus dem ByteArray erstellt. Dann habe ich dieses Bitmap an ein neues Bitmap übergeben und die Breite und Höhe auf die der Display Größen gesetzt. Dann übergebe ich das Bitmap um es mit dem Screenshot zu kombinieren....ich weiss, ist nicht die beste Lösung aber es geht erst einmal... wie es bei Photo Serien aussieht habe ich noch nicht getestet.

Was kann ich gegen OutOfMemoryError machen, ausser das Bitmap total zu zerschneiden? Ich hatte noch versucht, der Camera neue Parameter zuzuweisen mittels setPictureSize aber das scheint ihn nicht zu interessieren...

Ich poste einfach mal den gesamten Code, vielleicht kann mir ja jemand einen Tipp geben, wie ich das Problem am besten in den Griff bekomme. Hätte natürlich schon gerne das gesamte Camera Bild und darüber eben den Screenshot...

Hier der Code meiner MainActivity:

EDIT 1: Kennt jemand eine Adresse wo man Code posten kann, so dass er auch eingerückt ist?

1package com.example.androidcameratest;
2
3import java.io.File;
4import java.io.FileOutputStream;
5import java.io.IOException;
6import java.text.SimpleDateFormat;
7import java.util.Date;
8
9import android.annotation.SuppressLint;
10import android.app.Activity;
11import android.graphics.Bitmap;
12import android.graphics.BitmapFactory;
13import android.graphics.Canvas;
14import android.graphics.PixelFormat;
15import android.graphics.drawable.BitmapDrawable;
16import android.hardware.Camera;
17import android.hardware.Camera.Parameters;
18import android.hardware.Camera.PictureCallback;
19import android.hardware.Camera.ShutterCallback;
20import android.os.Bundle;
21import android.os.Environment;
22import android.view.Display;
23import android.view.SurfaceHolder;
24import android.view.SurfaceView;
25import android.view.View;
26import android.widget.Button;
27
28@SuppressLint("NewApi")
29public class MainActivity extends Activity implements SurfaceHolder.Callback {
30
31 Camera camera;
32 SurfaceView surfaceView;
33 SurfaceHolder surfaceHolder;
34 boolean previewing = false;
35 private Bitmap screenBmp = null;
36 private Bitmap cameraBmp = null;
37 private String picturefilename;
38
39 /** Called when the activity is first created. */
40 @Override
41 public void onCreate(Bundle savedInstanceState) {
42 super.onCreate(savedInstanceState);
43 setContentView(R.layout.main);
44 createFolder();
45 Button buttonStartCameraPreview = (Button) findViewById(R.id.startcamerapreview);
46 Button buttonStopCameraPreview = (Button) findViewById(R.id.stopcamerapreview);
47
48 getWindow().setFormat(PixelFormat.UNKNOWN);
49 surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
50 surfaceHolder = surfaceView.getHolder();
51 surfaceHolder.addCallback(this);
52 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
53
54 buttonStartCameraPreview
55 .setOnClickListener(new Button.OnClickListener() {
56
57 @Override
58 public void onClick(View v) {
59 // TODO Auto-generated method stub
60 if (!previewing) {
61
62 if (camera != null) {
63 try {
64 System.out.println("Hier bin ich");
65 camera.setPreviewDisplay(surfaceHolder);
66 camera.setDisplayOrientation(90);
67
68 camera.startPreview();
69
70 previewing = true;
71 } catch (IOException e) {
72 // TODO Auto-generated catch block
73 e.printStackTrace();
74 }
75 }
76 }
77 }
78 });
79
80 buttonStopCameraPreview
81 .setOnClickListener(new Button.OnClickListener() {
82
83 @Override
84 public void onClick(View v) {
85 // TODO Auto-generated method stub
86 if (camera != null && previewing) {
87 camera.stopPreview();
88 camera.release();
89 camera = null;
90
91 previewing = false;
92 }
93 }
94 });
95
96 Button buttonTakePicture = (Button) findViewById(R.id.takephoto);
97 buttonTakePicture.setOnClickListener(new Button.OnClickListener() {
98
99 @Override
100 public void onClick(View arg0) {
101 // TODO Auto-generated method stub
102 takeScreenshot();
103 camera.takePicture(myShutterCallback, myPictureCallback_RAW,
104 myPictureCallback_JPG);
105 }
106 });
107 }
108
109 private void createFolder() {
110 File dir = Environment.getExternalStorageDirectory();
111 File myDir = new File(dir, "CameraOverlay");
112 if (myDir.exists() && myDir.isDirectory()) {
113
114 } else {
115 boolean created = myDir.mkdir();
116 System.out.println("Folder created : " + created);
117
118 }
119 }
120
121 ShutterCallback myShutterCallback = new ShutterCallback() {
122
123 @Override
124 public void onShutter() {
125 // TODO Auto-generated method stub
126
127 }
128 };
129
130 PictureCallback myPictureCallback_RAW = new PictureCallback() {
131
132 @Override
133 public void onPictureTaken(byte[] arg0, Camera arg1) {
134 // TODO Auto-generated method stub
135
136 }
137 };
138
139 PictureCallback myPictureCallback_JPG = new PictureCallback() {
140
141 @Override
142 public void onPictureTaken(byte[] arg0, Camera arg1) {
143
144 Bitmap bmpSource = BitmapFactory.decodeByteArray(arg0, 0,
145 arg0.length);
146 Display display = getWindowManager().getDefaultDisplay();
147 int width = display.getWidth();
148 int height = display.getHeight();
149 cameraBmp = Bitmap.createBitmap(bmpSource, 0, 0, width, height);
150 checkBmps();
151 camera.startPreview();
152 }
153 };
154
155 private void takeScreenshot() {
156 View view = findViewById(R.id.rootview);
157 View v1 = view.getRootView();
158 v1.setDrawingCacheEnabled(true);
159 Bitmap sourceScreenBmp = v1.getDrawingCache();
160
161 BitmapDrawable alphaBmp = new BitmapDrawable(sourceScreenBmp);
162 alphaBmp.setAlpha(255);
163 screenBmp = alphaBmp.getBitmap();
164 screenBmp.setHasAlpha(true);
165 checkBmps();
166 }
167
168 private void checkBmps() {
169 if (screenBmp != null && cameraBmp != null) {
170 combineImages(cameraBmp, screenBmp);
171 } else {
172 System.out.println("Irgendwas ist hier doch faul :(");
173 }
174 }
175
176 public Bitmap combineImages(Bitmap c, Bitmap s) {
177 Bitmap cs = null;
178
179 int width, height = 0;
180
181 if (c.getWidth() > s.getWidth()) {
182 System.out.println("Unterschiedliche Breite");
183 width = c.getWidth() + s.getWidth();
184 height = c.getHeight();
185 } else {
186 System.out.println("Gleiche Breite");
187 width = s.getWidth() + s.getWidth();
188 height = c.getHeight();
189 }
190
191 cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
192
193 Canvas comboImage = new Canvas(cs);
194
195 comboImage.drawBitmap(c, 0f, 0f, null);
196 comboImage.drawBitmap(s, 0f, 0f, null);
197
198 SimpleDateFormat date = new SimpleDateFormat("ddMMyyyyhhmmss");
199 picturefilename = date.format(new Date());
200 File root = Environment.getExternalStorageDirectory();
201 File file = new File(root, "/CameraOverlay/" + picturefilename + ".jpg");
202 System.out.println("Nicht leer");
203 FileOutputStream fos = null;
204
205 try {
206 fos = new FileOutputStream(file);
207 if (fos != null) {
208 cs.compress(Bitmap.CompressFormat.JPEG, 100, fos);
209 fos.close();
210 }
211 } catch (Exception e) {
212 e.printStackTrace();
213 }
214
215 return cs;
216 }
217
218 @Override
219 public void surfaceChanged(SurfaceHolder holder, int format, int width,
220 int height) {
221 // TODO Auto-generated method stub
222
223 }
224
225 @Override
226 public void surfaceCreated(SurfaceHolder holder) {
227 // TODO Auto-generated method stub
228 camera = Camera.open();
229 Parameters para = camera.getParameters();
230 para.setPictureSize(400, 400);
231 camera.setParameters(para);
232 }
233
234 @Override
235 public void surfaceDestroyed(SurfaceHolder holder) {
236 // TODO Auto-generated method stub
237
238 }
239}

Danke und Grüße

— geändert am 24.08.2012, 04:27:14

Antworten
Jochen K.
  • Forum-Beiträge: 33

24.08.2012, 17:53:13 via Website

Hallo zusammen!

Ich habe bezüglich des Projektes heute morgen noch ein wenig länger gemacht und bin ein kleines Stückchen weiter gekommen. Mittels
1BitmapFactory.Options options = new BitmapFactory.Options();
2 options.inSampleSize = 3;
3 cameraBmp = BitmapFactory.decodeByteArray(arg0, 0, arg0.length,options);

kann ich scheinbar die Größe der Dateien verringern. Konnte dadurch sogar Photo aufnehmen in der Originalgröße. Allerdings pass dann der Screenshot nicht mehr auf das Bild, da das Foto von der Camera deutllich größer ist. Eine Aufnahme pro Sekunde kann ich derzeit Aufnehmen und auch wegspeichern aber nach ca. 9 Fotos bekomme ich dann wieder die Fehlermeldung OutOfMemoryError.

Nun habe ich mich gerade dazu entschieden, die Aufgenommen Fotos in jeweils einem BitmapArray zu legen und wenn der Aufnahmeprozess beendet ist, diese dann zu verarbeiten und wegzuspeichern. Ggf. auch in einem zweiten Task... ich denke mal, dass ich zuviele Resourcen derzeit anspreche und ich deshalb die Meldung bekomme.

Dann habe ich weiterhin auf die Suche nach einer Lösung bzgl. das rendern eines Videos aus Bildern gemacht und bin einmal auf ffmpeg und Xuggle gestoßen. Das Xuggle soll aber angeblich nur für den Gebrauch auf Desktop Endgeräten gedacht sein, auch wenn es schon auf Androids umgestezt wurde. Und zu ffmpeg finde ich leider nicht genügend Informationen, wie ich das umsetzen könnte.

Kennt sich jemand mit ffmpeg aus oder hat damit schon einmal rumgespielt? Ich würde gerne wissen, ob es sich überhaupt dafür eigenet videos aus einzelnen images zu rendern?!

Wenn ich hier durch bin, würde ich auch gerne den gesamten Code öffentlich posten, da ich bereits hunderte Threads gelesen habe, die auch nach solchen Lösungen suchen. Ist vielleicht nicht der perfekte Code, aber dafür dass ich gerade mal seit 2-3 Monaten mit Java arbeite, denke ich, dass es schon ganz ok ist. Und vielleicht hilft es dem einem oder anderen ja auch. Denn super häufig wird nach einer Lösung gesucht, wie man Elemente über einer Camera Preview anzeigt und diese auch ggf. mit aufnimmt.

Naja gut okay. Wenn also jemand was weiss bzgl. ffmpeg oder eine andere Idee hat, wie ich am besten ein Video aus einzelnen Images erstellen kann, dann bitte melden. Würde mich wirklich riesig freuen ;)

Grüße und besten Danke!

EDIT: Ich stehe gerade vor folgendem Problem: Die Camera Preview kann ich ja mittels
1camera.setDisplayOrientation(90)
korrekt darstellen, da bei mir auf dem handy ansonsten die preview irgendwie verdreht angezeit wird. Nun ist es aber so, dass die Aufgenommenen Fotos anders dargestellt werden, also um 90 Grad gegen den Uhrzeigersinn gekippt. Die darauf gerenderten Screenshot wiederum werden korrekt dargestellt. Weiss da jemand abhilfe?

1@Override
2 public void surfaceCreated(SurfaceHolder holder) {
3 // TODO Auto-generated method stub
4 int width, height;
5 camera = Camera.open();
6 Parameters para = camera.getParameters();
7 width = para.getPreviewSize().width;
8 height = para.getPreviewSize().height;
9 para.setPictureSize(width, height);
10 para.setRotation(90);
11
12
13 camera.setParameters(para);
14 camera.startPreview();
15 }

Das hat es leider nicht gebracht....

— geändert am 24.08.2012, 21:34:16

Antworten
Jochen K.
  • Forum-Beiträge: 33

26.08.2012, 04:16:22 via Website

Ich konnte das Problem, Screenshots von der Camera Preview aufzunehmen Dank dem Thread von ilyas https://www.nextpit.de/de/android/forum/thread/445103/SurfaceView-getDrawingCache-from-Camera und mit dessen Hilfe lösen!

Nur das aufnehmen von Videos geht natürlich nicht. Nun suche ich noch nach einer Lösung, um auf dem Android aus den einzelnen Bitmaps eine Video Datei zu erstellen. Natürlich ohne Hilfe von externen Tools. Das wäre ja kein Thema ;) Also, wenn jemand eine Idee oder eine Lösung dazu hat oder zumindest einen Ansatz, ich nehme sie gerne an :D

Danke und Gute Nacht ;)

Antworten