是否可以从同一活动中录制当前跑步活动的屏幕视频?
我知道如何采取当前活动的屏幕截图,但不知道采取屏幕视频记录。我该怎么开始呢?我不知道如何开始。
普通的Android应用程序缺乏捕获帧缓冲区的权限(具体来说,它们不是AID_GRAPHICS group的成员)。这是出于安全原因——否则他们可能会从软键盘窥探密码等。因此,一般来说,如果没有一些绕过特权问题的方法,你就无法从Android应用程序中捕获屏幕。
您可以或多或少地捕获当前由应用程序占用的屏幕区域的快照,方法是遍历到视图层次结构中的顶部视图,并使用View.draw(画布)将其绘制成位图,但是这不会记录状态栏,软键盘,OpenGL表面等。
如果你想做得更好,你需要使用一个外部工具。工具需要root或使用ADB接口,因为通过ADB接口启动的进程具有AID_GRAPHICS特权。使用后一种方法,非特权应用程序可以连接到特权服务器进行录制。
工具大致可分为以下几类:
>
仅限根用户的帧缓冲记录器应用程序(例如Screencast)。这些记录直接来自/dev/graphics/fb0设备,但仅适用于帧缓冲区可读的设备(例如,不适用于Tegra 2 Nexus 7)。
仅限根用户的屏幕捕获录制器应用程序(例如SCR、Rec等)。它们通过SurfaceFlinger捕捉屏幕,并在更广泛的设备上工作。
非根屏幕捕获记录器应用程序(例如,Recordable,Ascrecorder)。这些要求用户在通过主机连接时启用通用串行总线调试并启动守护程序。此后,在设备重新启动之前,不需要主机电脑。也可以录制音频。
ADB工具(例如Android 4.4上的内置屏幕记录器)。要求您通过USB连接,但无法捕获音频。
为了完整起见,还有一些USB工具(例如Mobizen)可以通过USB传输屏幕(受低USB带宽限制,无法录制音频),一些设备还可以通过wifi传输屏幕,然后可以在单独的设备上捕获。
编辑:这个答案被丹佩下面的答案所取代。
从应用程序中以编程方式录制视频需要root访问权限。你会注意到,Play Store中可用于执行此操作的应用程序在其应用程序描述中的显著列表“REQUIRES ROOT”。您还将注意到,这种方法可能也有一些特定的硬件要求(“在Galaxy Nexus或Tegra 2/3上不起作用……”来自Screencast Video Recorder应用程序的描述。
我自己从来没有写过这段代码,但是我已经对所需的方法有了一个非常高层次的想法。从这篇文章中可以看出,您必须通过“/dev/图形/fb0”访问帧缓冲区数据。帧缓冲区的访问模式是660,这意味着您需要根访问才能访问它。一旦你有了根访问权限,你就可以使用帧缓冲区数据来创建屏幕截图(这个项目可能适用于这个任务),然后从这些屏幕截图中创建视频(参见关于如何从图像序列创建视频的另一个SO问题)。
我使用过Screencast应用程序,它在三星Note上运行良好。我怀疑这是他们采取的基本方法。
因为Lollipop,我们可以使用媒体投影API!(API 21)
以下是我用于录制的代码,请注意,我们首先需要获得用户对此的权限;)
private static final int CAST_PERMISSION_CODE = 22;
private DisplayMetrics mDisplayMetrics;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private MediaRecorder mMediaRecorder;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMediaRecorder = new MediaRecorder();
mProjectionManager = (MediaProjectionManager) getSystemService
(Context.MEDIA_PROJECTION_SERVICE);
getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);
prepareRecording();
}
private void startRecording() {
// If mMediaProjection is null that means we didn't get a context, lets ask the user
if (mMediaProjection == null) {
// This asks for user permissions to capture the screen
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), CAST_PERMISSION_CODE);
return;
}
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
private void stopRecording() {
if (mMediaRecorder != null) {
mMediaRecorder.stop();
mMediaRecorder.reset();
}
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
}
if (mMediaProjection != null) {
mMediaProjection.stop();
}
prepareRecording();
}
public String getCurSysDate() {
return new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date());
}
private void prepareRecording() {
try {
mMediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
return;
}
final String directory = Environment.getExternalStorageDirectory() + File.separator + "Recordings";
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
Toast.makeText(this, "Failed to get External Storage", Toast.LENGTH_SHORT).show();
return;
}
final File folder = new File(directory);
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
String filePath;
if (success) {
String videoName = ("capture_" + getCurSysDate() + ".mp4");
filePath = directory + File.separator + videoName;
} else {
Toast.makeText(this, "Failed to create Recordings directory", Toast.LENGTH_SHORT).show();
return;
}
int width = mDisplayMetrics.widthPixels;
int height = mDisplayMetrics.heightPixels;
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(width, height);
mMediaRecorder.setOutputFile(filePath);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != CAST_PERMISSION_CODE) {
// Where did we get this request from ? -_-
Log.w(TAG, "Unknown request code: " + requestCode);
return;
}
if (resultCode != RESULT_OK) {
Toast.makeText(this, "Screen Cast Permission Denied :(", Toast.LENGTH_SHORT).show();
return;
}
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
// TODO Register a callback that will listen onStop and release & prepare the recorder for next recording
// mMediaProjection.registerCallback(callback, null);
mVirtualDisplay = getVirtualDisplay();
mMediaRecorder.start();
}
private VirtualDisplay getVirtualDisplay() {
screenDensity = mDisplayMetrics.densityDpi;
int width = mDisplayMetrics.widthPixels;
int height = mDisplayMetrics.heightPixels;
return mMediaProjection.createVirtualDisplay(this.getClass().getSimpleName(),
width, height, screenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null /*Handler*/);
}
这不是最终的代码,但一个良好的基础开始:)
是迄今为止用Java捕获麦克风输入的最简单方法。我想对我用屏幕视频(在屏幕录制软件中)捕获的音频进行编码,以便用户可以创建教程、幻灯片盒等。 我使用对视频进行编码<他们确实有一个用视频编码音频的教程,但他们从文件中获取音频。就我而言,音频是实时的 参考文献: 1. DavaDoc for TargetDataLine:http://docs.oracle.com/javase/1.4.2/docs
他们的任何源代码或示例项目,允许录制应用程序正在运行的屏幕的视频。我必须制作一个能够在Android设备中录制应用程序屏幕视频的应用程序。我搜索了这个,但什么也没找到。
我的任务是在webview中记录用户活动,换句话说,我需要在用户在webview中导航时创建一个mp4视频文件。非常具有挑战性:)我在Android 4.3中引入的字体MediaCodec:被扩展为包括一种通过Surface(通过createInputSurface方法)提供输入的方法。这允许输入来自相机预览或OpenGL ES渲染。我甚至找到了一个例子,你可以记录一个用opengl编写的游戏:h
问题内容: 我想找出一个如何使用Java捕获截屏视频。我知道使用Robot类可以获取屏幕截图,但是如何将其捕获为视频并将其上传到服务器呢?那将如何工作? 想法? 问题答案: 使用纯Java解决方案,我怀疑它是否会起作用,但这当然取决于您对“视频”的解释。 在分辨率为1920x1200的台式机上,使用Java Robot捕获整个屏幕时,每秒可以获取约20帧。由于每个图像都包含> 6 MB的未压缩数据
我的有问题,当我在手机上启动应用程序时,它会显示约0.5秒的白色屏幕。扩展了,在中,我声明为启动器,肖像模式为。 代码: XML: