Am developing a simple camera app. I have code that takes screenshot of the whole activity and writes it to the SD card. The problem is that the SurfaceView returns a black screen.
I would like to know how to independently take a screenshot of the SurfaceView only. Here is the code that takes the screenshot of the whole activity.
findViewById(R.id.screen).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final RelativeLayout layout = (RelativeLayout) findViewById(R.id.RelativeLayout1);
layout.setVisibility(RelativeLayout.GONE);
Bitmap bitmap = takeScreenshot();
Toast.makeText(getApplicationContext(),"Please Wait", Toast.LENGTH_LONG).show();
saveBitmap(bitmap);
}
});
public Bitmap takeScreenshot() {
View rootView = findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
public void saveBitmap(Bitmap bitmap) {
final MediaPlayer cheer = MediaPlayer.create(PicShot.this, R.raw.shutter);
cheer.start();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".png";
final RelativeLayout layout = (RelativeLayout) findViewById(R.id.RelativeLayout1);
File imagePath = new File(Environment.getExternalStorageDirectory() + "/" + fname);
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
layout.setVisibility(RelativeLayout.VISIBLE);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
Uri uri = Uri.fromFile(imagePath);
share.putExtra(Intent.EXTRA_STREAM,uri);
startActivity(Intent.createChooser(share, "Share Image"));
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
The SurfaceView's surface is independent of the surface on which View elements are drawn. So capturing the View contents won't include the SurfaceView.
You need to capture the SurfaceView contents separately and perform your own composition step. The easiest way to do the capture is probably to just re-render the contents, but use an off-screen bitmap as the target rather than the surface. If you're rendering with GLES to an off-screen pbuffer, you can use glReadPixels() before you swap buffers.
Update: Grafika's "texture from camera" activity demonstrates handling live video from the camera with OpenGL ES. EglSurfaceBase#saveFrame() shows how to capture GLES rendering to a Bitmap.
Update: See also this answer, which provides a bit more background.
Just copy and past code
Note: only For API level >= 24
private void takePhoto() {
// Create a bitmap the size of the scene view.
final Bitmap bitmap = Bitmap.createBitmap(
surfaceView.getWidth(),
surfaceView.getHeight(),
Bitmap.Config.ARGB_8888
);
// Create a handler thread to offload the processing of the image.
final HandlerThread handlerThread = new HandlerThread("PixelCopier");
handlerThread.start();
// Make the request to copy.
PixelCopy.request(holder.videoView, bitmap, (copyResult) -> {
if (copyResult == PixelCopy.SUCCESS) {
Log.e(TAG,bitmap.toString());
String name = String.valueOf(System.currentTimeMillis() + ".jpg");
imageFile = ScreenshotUtils.store(bitmap,name);
} else {
Toast toast = Toast.makeText(
getViewActivity(),
"Failed to copyPixels: " + copyResult,
Toast.LENGTH_LONG
);
toast.show();
}
handlerThread.quitSafely();
}, new Handler(handlerThread.getLooper()));
}
My situation related with ExoPlayer, need get bitmap of current frame
Works on API >= 24:
private val copyFrameHandler = Handler()
fun getFrameBitmap(callback: FrameBitmapCallback) {
when(val view = videoSurfaceView) {
is TextureView -> callback.onResult(view.bitmap)
is SurfaceView -> {
val bitmap = Bitmap.createBitmap(
videoSurfaceView.getWidth(),
videoSurfaceView.getHeight(),
Bitmap.Config.ARGB_8888
)
copyFrameHandler.removeCallbacksAndMessages(null)
PixelCopy.request(view, bitmap, { copyResult: Int ->
if (copyResult == PixelCopy.SUCCESS) {
callback.onResult(bitmap)
} else {
callback.onResult(null)
}
}, copyFrameHandler)
}
else -> callback.onResult(null)
}
}
fun onDestroy() {
copyFrameHandler.removeCallbacksAndMessages(null)
}
interface FrameBitmapCallback {
fun onResult(bitmap: Bitmap?)
}
If your situation allows it, using a TextureView instead of a SurfaceView will make this problem a lot easier to solve. It has a method getBitmap() that returns a Bitmap of the current frame on the TextureView.
This is how I do it. Put this method in some Util class:
/**
* Pixel copy to copy SurfaceView/VideoView into BitMap
*/
fun usePixelCopy(videoView: SurfaceView, callback: (Bitmap?) -> Unit) {
val bitmap: Bitmap = Bitmap.createBitmap(
videoView.width,
videoView.height,
Bitmap.Config.ARGB_8888
);
try {
// Create a handler thread to offload the processing of the image.
val handlerThread = HandlerThread("PixelCopier");
handlerThread.start();
PixelCopy.request(
videoView, bitmap,
PixelCopy.OnPixelCopyFinishedListener { copyResult ->
if (copyResult == PixelCopy.SUCCESS) {
callback(bitmap)
}
handlerThread.quitSafely();
},
Handler(handlerThread.looper)
)
} catch (e: IllegalArgumentException) {
callback(null)
// PixelCopy may throw IllegalArgumentException, make sure to handle it
e.printStackTrace()
}
}
Usage:
usePixelCopy(videoView) { bitmap: Bitmap? ->
processBitMp(bitmap)
}
Note: VideoView is a subclass of SurfaceView, so this method can take screenshot of video View as well.
For those of us looking for a solution for API <= 24, this is what I did as a workaround. When user clicks button for capture, close the preview captureSession and create a new captureSession for still image capture.
mCaptureSession.stopRepeating();
mCaptureSession.abortCaptures();
mCaptureSession.close();
mCaptureSession = null;
mPreviewReader = ImageReader.newInstance(previewSize.getWidth(), previewSize.getHeight(), ImageFormat.JPEG, MAX_IMAGES);
mPreviewReader.setOnImageAvailableListener(mImageAvailableListener, mBackgroundHandler);
mCameraDevice.createCaptureSession(
Arrays.asList(mPreviewReader.getSurface()),
//Arrays.asList(mSurface),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
mCaptureSession = cameraCaptureSession;
try {
final CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mPreviewReader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(mOrientation));
Log.d(TAG, "Capture request created.");
mCaptureSession.capture(captureBuilder.build(), mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException cae) {
Log.d(TAG, cae.toString());
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {}
},
mBackgroundHandler
);
Then at onImageAvailableListener, you can get the image with imageReader.acquireNextImage() to get the still captured image.
Related
I am using the video-view to play media and I want to take the screen shot of the current frame. I found some solutions which include using mediaMetaDataRetriever but that method is way too slow and does not perform well in many cases.
I can not use media player over texture view to capture view I knew that approach, because I need by default media controls in my app.
Is there any way to make that process fast?
My CODE:
public Bitmap getBitmapVideoView(){
MediaMetadataRetriever mediaMetadataRetriever;
mediaMetadataRetriever = new MediaMetadataRetriever();
try {
int currentPosition =videoView.getCurrentPosition();
mediaMetadataRetriever.setDataSource(getVideoURL(),new HashMap<String, String>());
Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(currentPosition*1000);
if (bitmap != null) {
// Canvas canvas = new Canvas(bitmap);
// textureview.draw(canvas);
return bitmap;
}
else{
return null;
}
}
catch (Exception e){
Log.i("Errorrr",e.getMessage());
return null;
}
finally {
try {
mediaMetadataRetriever.release();
}
catch (Exception e){
e.printStackTrace();
}
}
}
Approach:
Bitmap bitmap = Screenshot.INSTANCE.with((MainActivity)activity).setView(findViewById(R.id.relative)).setQuality(Quality.HIGH).getScreenshot();
LayoutInflater inflater = getLayoutInflater();
Toast toastShot = null;
View layout = inflater.inflate(R.layout.layout, (ViewGroup) findViewById(R.id.screen));
ImageView image = (ImageView) layout.findViewById(R.id.shot_image);
image.setImageBitmap(bitmap);
toastShot = new Toast(getApplicationContext());
toastShot.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toastShot.setDuration(Toast.LENGTH_LONG);
toastShot.setView(layout);
toastShot.show();
For taking screenshot you can use this library
implementation 'com.github.MindorksOpenSource:screenshot:v0.0.1'
And for taking screenshot just call this function on button click or any other event
var b = Screenshot.with(activity!!).setView(rl_imageText).setQuality(Quality.HIGH).getScreenshot()
Note: rl_imageText = This is the id of my xml relative layout of which i am taking screenshot.
It will provide you the bitmap of the screenshot and for saving it into the storage or getting path use the below mentioned function
private fun getImageUriFromBitmap(context: Context, bitmap: Bitmap): Uri {
val bytes = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes)
val path = MediaStore.Images.Media.insertImage(context.contentResolver, bitmap,"Title",null)
return Uri.parse(path.toString())
}
Note: Please mention if it will not work so that i will provide you other solution.
I'm trying to get fresco cached image from a fragment after a button click event to share the image bitmap in whatsapp!! Unfortunately it's very slow, after click the share button 2, 3 times code works!! I'm looking for better solution !!
ImageRequest imageRequest = ImageRequestBuilder
.newBuilderWithSource(Uri.parse("http://example.com/test,jpg"))// disck cached
.setRequestPriority(com.facebook.imagepipeline.common.Priority.HIGH)
.setLowestPermittedRequestLevel(ImageRequest.RequestLevel.DISK_CACHE)
.build();
// .setRequestPriority(Priority.HIGH)
DataSource<CloseableReference<CloseableImage>> dataSource =
imagePipeline.fetchDecodedImage(imageRequest, this);
try {
dataSource.subscribe(new BaseBitmapDataSubscriber() {
#Override
public void onNewResultImpl(#Nullable Bitmap bitmap) {
if (bitmap == null) {
Log.d(TAG, "Bitmap data source returned success, but bitmap null.");
return;
}
sharewithwhatsappBitmap(bitmap);
// The bitmap provided to this method is only guaranteed to be around
// for the lifespan of this method. The image pipeline frees the
// bitmap's memory after this method has completed.
//
// This is fine when passing the bitmap to a system process as
// Android automatically creates a copy.
//
// If you need to keep the bitmap around, look into using a
// BaseDataSubscriber instead of a BaseBitmapDataSubscriber.
}
#Override
public void onFailureImpl(DataSource dataSource) {
// No cleanup required here
Log.d(TAG, "Bitmap data source onFailureImpl");
}
}, CallerThreadExecutor.getInstance());
} finally {
if (dataSource != null) {
dataSource.close();
}
}
I'm using DraweeController in recyclerview, DraweeController is more optimized I guess !! but don't how to use it for getting one image with bitmap !!
public void sharewithwhatsappBitmap(Bitmap bitmap) {
String path = MediaStore.Images.Media.insertImage(getApplicationContext().getContentResolver(),
bitmap, "Image Description", null);
Uri bmpUri = Uri.parse(path);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
//shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Title Of The Post");
shareIntent.putExtra(Intent.EXTRA_TEXT, "https://play.google.com/store/apps/details?id=garbagebin.com.garbagebin");
shareIntent.setType("image/*");
//startActivity(Intent.createChooser(shareIntent, "Share Image"));
shareIntent.setPackage("com.whatsapp");
try {
startActivity(shareIntent);
} catch (android.content.ActivityNotFoundException ex) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.whatsapp")));
}
}
Log when first time it calls for bitmap:
v/unknown:AbstractDraweeController: controller 2a7f5b0e null -> 15: initialize
V/unknown:AbstractDraweeController: controller 2a7f5b0e 15: setHierarchy: com.facebook.drawee.generic.GenericDraweeHierarchy#20cc392f
I am writing tests using espresso,my app intends to phone camera, where i press the click button manually,and then it migrates to the next screen,I am not able to automate the image click button in test code,how can i access camera using code through which i can do the same.
Thanks.
You should not open the camera intent or you'll have no way of getting any resulting image back from it (without pressing the camera button manually).
Have a look at the Stubbing out the Camera section of this website:
https://guides.codepath.com/android/UI-Testing-with-Espresso#stubbing-out-the-camera
This way you test your activity by simulating an actual image "returned" to your app from the Camera.
Update
And this is the method I use to get a bitmap to test:
public static Bitmap getTestBitmap(Context context, String resourceName) {
Resources resources = context.getResources();
Bitmap ret = null;
int imageResource = resources.getIdentifier(
resourceName, "drawable", context.getPackageName());
Uri pictureUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ resources.getResourcePackageName(imageResource) + '/'
+ resources.getResourceTypeName(imageResource) + '/'
+ resources.getResourceEntryName(imageResource));
try {
ret = MediaStore.Images.Media.getBitmap(context.getContentResolver(), pictureUri);
} catch (Exception e) {
}
return ret;
}
And then I save the bitmap in internal storage and get the uri:
public static Uri saveToInternalStorage(Context context, Bitmap bitmapImage, String fileName) {
ContextWrapper cw = new ContextWrapper(context);
// path to /data/data/yourapp/app_data/pictures
File directory = cw.getDir("pictures", Context.MODE_PRIVATE);
// Create imageDir
File mypath = new File(directory, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (Exception e) {
}
}
return Uri.fromFile(new File(mypath.getAbsolutePath()));
}
I know this is late, but it's something I struggled with myself and I would like to post an answer to help someone else. Here is how you click the camera button from a chooser (after you set it up), you use UIAutomator, as suggested by PunitD in the comments of the original post. This will pick up from where the test is showing a chooser on the screen.
public static final int waitTimeNativeApi = 6000;
public static void await(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted while sleeping");
}
}
private void takePhoto() {
boolean usePixels = true;
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
UiObject titleTextUI = device.findObject(new UiSelector()
.className("android.widget.TextView")
.text("Camera")
);
try {
titleTextUI.clickTopLeft();
if (usePixels) {
takePhotoForPixels(device);
} else {
takePhotoForSamsung(device);
}
} catch (UiObjectNotFoundException unofe) {
unofe.printStackTrace();
}
}
private void takePhotoForPixels(UiDevice device) {
// close the app selector to go back to our app so we can carry on with Espresso
await(waitTimeNativeApi);
//TAP on the camera icon
device.click(device.getDisplayWidth() / 2, device.getDisplayHeight() - 100);
await(waitTimeNativeApi);
//Get the OK button
device.click(device.getDisplayWidth() / 2, device.getDisplayHeight() - 100);
await(waitTimeNativeApi);
}
private void takePhotoForSamsung(UiDevice device) throws UiObjectNotFoundException {
// close the app selector to go back to our app so we can carry on with Espresso
UiObject titleTextUI = device.findObject(new UiSelector()
.className("android.widget.TextView")
.text("Camera")
);
titleTextUI.clickTopLeft();
await(waitTimeNativeApi);
//TAP on the camera icon
device.click(device.getDisplayWidth() / 2, device.getDisplayHeight() - 50);
//Get the OK button
UiObject cameraOkUi = device.findObject(new UiSelector()
.className("android.widget.TextView")
.text("OK")
);
cameraOkUi.click();
await(waitTimeNativeApi);
}
In this way, you will take an actual photo and get the results back in onActivityResult.
I want to start the camera intent within my app to take a picture and save it to internal storage. I'm using the code of google developers page Capturing images or video.
In the processPictureWhenReady method I've implemented the following code to save the picture:
private void processPictureWhenReady(final String picturePath) {
Log.v("path processPictureWhenReady ", " " + picturePath);
final File pictureFile = new File(picturePath);
if (pictureFile.exists()) {
// The picture is ready; process it.
try {
Bitmap imageBitmap = BitmapFactory.decodeFile(picturePath);
int w = imageBitmap.getWidth();
int h = imageBitmap.getHeight();
Bitmap bm2 = Bitmap.createScaledBitmap(imageBitmap, w / 2,
h / 2, true);
imageBitmap = bm2.copy(bm2.getConfig(), true);
MediaStore.Images.Media.insertImage(getContentResolver(),
imageBitmap, "test", "Test");
} catch (Exception e) {
Log.e("Exc", e.getMessage());
}
}
The camera intent is starting and then I have "tap to accept" to take a picture. But then nothing happens. I have a log message in my onActivityResult method and noticed that the method is not beeing called.
This is a known issue. I have the same problem. I'm following the case here in the meantime
I've seen people try implementing the preview mode with SurfaceView (I haven't personally gotten it to work but it's worth a shot). Also check here for a similar problem.
I used this method it worked for me very well.
private void processPictureWhenReady(final String picturePath) {
final File pictureFile = new File(picturePath);
if(pictureFile.exists()){
}
if (pictureFile.exists()) {
} else {
final File parentDirectory = pictureFile.getParentFile();
FileObserver observer = new FileObserver(parentDirectory.getPath()) {
private boolean isFileWritten;
#Override
public void onEvent(int event, String path) {
if (!isFileWritten) {
// For safety, make sure that the file that was created in
// the directory is actually the one that we're expecting.
File affectedFile = new File(parentDirectory, path);
isFileWritten = (event == FileObserver.CLOSE_WRITE && affectedFile.equals(pictureFile));
if (isFileWritten) {
stopWatching();
// Now that the file is ready, recursively call
// processPictureWhenReady again (on the UI thread).
runOnUiThread(new Runnable() {
#Override
public void run() {
processPictureWhenReady(picturePath);
}
});
}
}
}
};
observer.startWatching();
}
}
I need to get a frame of a video file (it may be on sdcard, cache dir or app dir). I have package android.media in my application and inside I have class MediaMetadataRetriever. To get first frame into a bitmap, I use code:
public static Bitmap getVideoFrame(Context context, Uri videoUri) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
retriever.setDataSource(context, videoUri);
return retriever.captureFrame();
} catch (IllegalArgumentException ex) {
throw new RuntimeException();
} catch (RuntimeException ex) {
throw new RuntimeException();
} finally {
retriever.release();
}
}
But this it's not working. It throws an exception (java.lang.RuntimeException: setDataSource failed: status = 0x80000000) when I set data source. Do you know how to make this code to work? Or Do you have any similar (simple) solution without using ffmpeg or other external libraries? videoUri is a valid uri (media player can play video from that URI)
The following works for me:
public static Bitmap getVideoFrame(FileDescriptor FD) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(FD);
return retriever.getFrameAtTime();
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
} catch (RuntimeException ex) {
ex.printStackTrace();
} finally {
try {
retriever.release();
} catch (RuntimeException ex) {
}
}
return null;
}
Also works if you use a path instead of a filedescriptor.
Try this, I've used it and its working
public static Bitmap getVideoFrame(Context context, Uri uri) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(uri.toString(),new HashMap<String, String>());
return retriever.getFrameAtTime();
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
} catch (RuntimeException ex) {
ex.printStackTrace();
} finally {
try {
retriever.release();
} catch (RuntimeException ex) {
}
}
return null;
}
In place of uri you can directly pass your url .
I used this code and that is working for me. you can try this one.
if (Build.VERSION.SDK_INT >= 14) {
ffmpegMetaDataRetriever.setDataSource(
videoFile.getAbsolutePath(),
new HashMap<String, String>());
} else {
ffmpegMetaDataRetriever.setDataSource(videoFile
.getAbsolutePath());
}
I have the same mistake on my application. I saw on this site that
this is an unofficial way of doing it
and it will only work in cupcake (and
maybe later version). The Android team
does not guarantee that
libmedia_jni.so, which the java file
uses, will be included or have the
same interface in future versions.
http://osdir.com/ml/AndroidDevelopers/2009-06/msg02442.html
I have updated my phone to GingerBread and it doesn't work anymore.
Uri's are not very specific. Sometimes they refer to something in a bundle. They often need to be translated to an absolute path form. The other instance in which you used the Uri, it probably was smart enough to check what kind of Uri it was. This case that you have shown appears to be not looking very hard.
I was getting the same error using the ThumbnailUtils class http://developer.android.com/reference/android/media/ThumbnailUtils.html
It uses MediaMetadataRetriever under the hood and most of the time you can send it a filepath using this method with no problem:
public static Bitmap createVideoThumbnail (String filePath, int kind)
However, on Android 4.0.4, I kept getting the same error #gabi was seeing. Using a file descriptor instead solved the problem and still works for non-4.0.4 devices. I actually ended up subclassing ThumbnailUtils. Here is my subclass method:
public static Bitmap createVideoThumbnail(FileDescriptor fDescriptor, int kind)
{
Bitmap bitmap = null;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(fDescriptor);
bitmap = retriever.getFrameAtTime(-1);
}
catch (IllegalArgumentException ex) {
// Assume this is a corrupt video file
Log.e(LOG_TAG, "Failed to create video thumbnail for file description: " + fDescriptor.toString());
}
catch (RuntimeException ex) {
// Assume this is a corrupt video file.
Log.e(LOG_TAG, "Failed to create video thumbnail for file description: " + fDescriptor.toString());
} finally {
try {
retriever.release();
} catch (RuntimeException ex) {
// Ignore failures while cleaning up.
}
}
if (bitmap == null) return null;
if (kind == Images.Thumbnails.MINI_KIND) {
// Scale down the bitmap if it's too large.
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int max = Math.max(width, height);
if (max > 512) {
float scale = 512f / max;
int w = Math.round(scale * width);
int h = Math.round(scale * height);
bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
}
} else if (kind == Images.Thumbnails.MICRO_KIND) {
bitmap = extractThumbnail(bitmap,
TARGET_SIZE_MICRO_THUMBNAIL,
TARGET_SIZE_MICRO_THUMBNAIL,
OPTIONS_RECYCLE_INPUT);
}
return bitmap;
}
The exception is thrown also when the File doesn't exist. So before calling setDataSource() you'd better check if new File(url).exists().
so is there a specific way to get the frame from video as
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard, "myvideo.mp4");