- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试从我的 Samsung Galaxy S6(支持 1920x1080,约 30 fps)上的后置摄像头(面对脸部的摄像头)录制视频。如果不需要,我不想使用任何表面进行预览,因为这只会在后台发生。
我似乎让它工作了,但输出文件无法以实际正确的方式播放。在我的 Windows 10 PC 上,Windows Media Player 将显示第一帧然后播放音频,VLC 不会显示任何帧。在我的手机上,录制的文件可以播放,但不能完全播放。它将保持第一帧 5-8 秒,然后在最后,剩余时间变为 0,显示的总时间发生变化,然后实际视频帧开始播放。在我的 Mac (10.9.5) 上,Quicktime 不会显示视频(虽然没有错误),但 Google Picasa 可以完美播放。我想在我的 PC 上试用 Picasa 看看它是否在那里工作,但我无法再下载 Google Picasa,因为已经日落了。
我尝试安装我找到的适用于 Windows 的编解码器包,但没有解决任何问题。 MediaInfo v0.7.85 报告有关该文件的信息:
GeneralComplete name : C:\...\1465655479915.mp4Format : MPEG-4Format profile : Base Media / Version 2Codec ID : mp42 (isom/mp42)File size : 32.2 MiBDuration : 15s 744msOverall bit rate : 17.1 MbpsEncoded date : UTC 2016-06-11 14:31:50Tagged date : UTC 2016-06-11 14:31:50com.android.version : 6.0.1VideoID : 1Format : AVCFormat/Info : Advanced Video CodecFormat profile : High@L4Format settings, CABAC : YesFormat settings, ReFrames : 1 frameFormat settings, GOP : M=1, N=30Codec ID : avc1Codec ID/Info : Advanced Video CodingDuration : 15s 627msBit rate : 16.2 MbpsWidth : 1 920 pixelsHeight : 1 080 pixelsDisplay aspect ratio : 16:9Frame rate mode : VariableFrame rate : 0.000 (0/1000) fpsMinimum frame rate : 0.000 fpsMaximum frame rate : 30.540 fpsColor space : YUVChroma subsampling : 4:2:0Bit depth : 8 bitsScan type : ProgressiveStream size : 0.00 Byte (0%)Source stream size : 31.7 MiB (98%)Title : VideoHandleLanguage : EnglishEncoded date : UTC 2016-06-11 14:31:50Tagged date : UTC 2016-06-11 14:31:50mdhd_Duration : 15627AudioID : 2Format : AACFormat/Info : Advanced Audio CodecFormat profile : LCCodec ID : 40Duration : 15s 744msBit rate mode : ConstantBit rate : 256 KbpsChannel(s) : 2 channelsChannel positions : Front: L RSampling rate : 48.0 KHzFrame rate : 46.875 fps (1024 spf)Compression mode : LossyStream size : 492 KiB (1%)Title : SoundHandleLanguage : EnglishEncoded date : UTC 2016-06-11 14:31:50Tagged date : UTC 2016-06-11 14:31:50
The code that I am using to create this is:
package invisiblevideorecorder;
import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
/**
* @author Mark
* @since 6/10/2016
*/
public class InvisibleVideoRecorder {
private static final String TAG = "InvisibleVideoRecorder";
private final CameraCaptureSessionStateCallback cameraCaptureSessionStateCallback = new CameraCaptureSessionStateCallback();
private final CameraDeviceStateCallback cameraDeviceStateCallback = new CameraDeviceStateCallback();
private MediaRecorder mediaRecorder;
private CameraManager cameraManager;
private Context context;
private CameraDevice cameraDevice;
private HandlerThread handlerThread;
private Handler handler;
public InvisibleVideoRecorder(Context context) {
this.context = context;
handlerThread = new HandlerThread("camera");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
try {
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
final String filename = context.getExternalFilesDir(Environment.DIRECTORY_MOVIES).getAbsolutePath() + File.separator + System.currentTimeMillis() + ".mp4";
mediaRecorder.setOutputFile(filename);
Log.d(TAG, "start: " + filename);
// by using the profile, I don't think I need to do any of these manually:
// mediaRecorder.setVideoEncodingBitRate(16000000);
// mediaRecorder.setVideoFrameRate(30);
// mediaRecorder.setCaptureRate(30);
// mediaRecorder.setVideoSize(1920, 1080);
// mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
// mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
// Log.d(TAG, "start: 1 " + CamcorderProfile.hasProfile(CameraMetadata.LENS_FACING_BACK, CamcorderProfile.QUALITY_1080P));
// true
// Log.d(TAG, "start: 2 " + CamcorderProfile.hasProfile(CameraMetadata.LENS_FACING_BACK, CamcorderProfile.QUALITY_HIGH_SPEED_1080P));
// false
// Log.d(TAG, "start: 3 " + CamcorderProfile.hasProfile(CameraMetadata.LENS_FACING_BACK, CamcorderProfile.QUALITY_HIGH));
// true
CamcorderProfile profile = CamcorderProfile.get(CameraMetadata.LENS_FACING_BACK, CamcorderProfile.QUALITY_1080P);
Log.d(TAG, "start: profile " + ToString.inspect(profile));
// start: 0 android.media.CamcorderProfile@114016694 {
// audioBitRate: 256000
// audioChannels: 2
// audioCodec: 3
// audioSampleRate: 48000
// duration: 30
// fileFormat: 2
// quality: 6
// videoBitRate: 17000000
// videoCodec: 2
// videoFrameHeight: 1080
// videoFrameRate: 30
// videoFrameWidth: 1920
// }
mediaRecorder.setOrientationHint(0);
mediaRecorder.setProfile(profile);
mediaRecorder.prepare();
} catch (IOException e) {
Log.d(TAG, "start: exception" + e.getMessage());
}
}
public void start() {
Log.d(TAG, "start: ");
cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try {
cameraManager.openCamera(String.valueOf(CameraMetadata.LENS_FACING_BACK), cameraDeviceStateCallback, handler);
} catch (CameraAccessException | SecurityException e) {
Log.d(TAG, "start: exception " + e.getMessage());
}
}
public void stop() {
Log.d(TAG, "stop: ");
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
cameraDevice.close();
try {
handlerThread.join();
} catch (InterruptedException e) {
}
}
private class CameraCaptureSessionStateCallback extends CameraCaptureSession.StateCallback {
private final static String TAG = "CamCaptSessionStCb";
@Override
public void onActive(CameraCaptureSession session) {
Log.d(TAG, "onActive: ");
super.onActive(session);
}
@Override
public void onClosed(CameraCaptureSession session) {
Log.d(TAG, "onClosed: ");
super.onClosed(session);
}
@Override
public void onConfigured(CameraCaptureSession session) {
Log.d(TAG, "onConfigured: ");
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.d(TAG, "onConfigureFailed: ");
}
@Override
public void onReady(CameraCaptureSession session) {
Log.d(TAG, "onReady: ");
super.onReady(session);
try {
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
builder.addTarget(mediaRecorder.getSurface());
CaptureRequest request = builder.build();
session.setRepeatingRequest(request, null, handler);
mediaRecorder.start();
} catch (CameraAccessException e) {
Log.d(TAG, "onConfigured: " + e.getMessage());
}
}
@Override
public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
Log.d(TAG, "onSurfacePrepared: ");
super.onSurfacePrepared(session, surface);
}
}
private class CameraDeviceStateCallback extends CameraDevice.StateCallback {
private final static String TAG = "CamDeviceStateCb";
@Override
public void onClosed(CameraDevice camera) {
Log.d(TAG, "onClosed: ");
super.onClosed(camera);
}
@Override
public void onDisconnected(CameraDevice camera) {
Log.d(TAG, "onDisconnected: ");
}
@Override
public void onError(CameraDevice camera, int error) {
Log.d(TAG, "onError: ");
}
@Override
public void onOpened(CameraDevice camera) {
Log.d(TAG, "onOpened: ");
cameraDevice = camera;
try {
camera.createCaptureSession(Arrays.asList(mediaRecorder.getSurface()), cameraCaptureSessionStateCallback, handler);
} catch (CameraAccessException e) {
Log.d(TAG, "onOpened: " + e.getMessage());
}
}
}
}
我遵循了 Android 源代码(测试和应用程序)以及我在 github 上找到的几个示例,以解决这个问题,因为 camera2 API 还没有很好的文档记录。
有什么明显的地方我做错了吗?或者,我是否只是在我的 Mac 上缺少用于 Quicktime 的编解码器以及在我的 PC 上用于 Windows Media Player 和 VLC 的编解码器?我还没有尝试在 Linux 上播放这些文件,所以我不知道那里会发生什么。哦,如果我将 mp4 文件上传到 photos.google.com,它们也可以在那里完全正确地播放。
谢谢!标记
最佳答案
我的团队在开发基于 Camera2 API 的插件时遇到了类似的问题,但它只影响了 Samsung Galaxy S7(我们还有用于测试的 S6 没有出现此行为)。
该问题似乎是由三星相机固件中的错误引起的,并在设备退出深度 sleep (Android 6.0 Marshmallow 中的超低功耗模式)时触发。从深度 sleep 中恢复后,使用 Camera2 MediaRecorder 捕获和编码的任何视频的第一帧都具有非常长的帧持续时间 - 有时与视频本身的总持续时间一样长或更长。
因此,在播放时,第一帧会显示这么长时间,同时音频会继续播放。第一帧显示完毕后,其余帧将正常播放。
我们发现其他人也有类似的问题discussing the issue on GitHub
The issue is a deep sleep problem on some devices running Marshmallow. It appears to be CPU related as an S7 on Verizon doesn't have the issue, but an S7 on AT&T does have the issue. I've seen this on an S6 Verizon phone when it updated to Marshmallow.
In order to replicate, reboot a device while connected to USB. Run the sample. All should be ok. Then, disconnect the device, let it go into deep sleep (screen off, no movement for 5? minutes), and try again. The issue will appear once the device has gone into deep sleep.
我们最终使用了 cybaker's proposed workaround ;也就是说,当创建视频文件时,检查视频第一帧的持续时间。如果它看起来不正确,请使用合理的帧持续时间重新编码视频:
DataSource channel = new FileDataSourceImpl(rawFile);
IsoFile isoFile = new IsoFile(channel);
List<TrackBox> trackBoxes = isoFile.getMovieBox().getBoxes(TrackBox.class);
boolean sampleError = false;
for (TrackBox trackBox : trackBoxes) {
TimeToSampleBox.Entry firstEntry = trackBox.getMediaBox().getMediaInformationBox().getSampleTableBox().getTimeToSampleBox().getEntries().get(0);
// Detect if first sample is a problem and fix it in isoFile
// This is a hack. The audio deltas are 1024 for my files, and video deltas about 3000
// 10000 seems sufficient since for 30 fps the normal delta is about 3000
if(firstEntry.getDelta() > 10000) {
sampleError = true;
firstEntry.setDelta(3000);
}
}
if(sampleError) {
Movie movie = new Movie();
for (TrackBox trackBox : trackBoxes) {
movie.addTrack(new Mp4TrackImpl(channel.toString() + "[" + trackBox.getTrackHeaderBox().getTrackId() + "]" , trackBox));
}
movie.setMatrix(isoFile.getMovieBox().getMovieHeaderBox().getMatrix());
Container out = new DefaultMp4Builder().build(movie);
//delete file first!
FileChannel fc = new RandomAccessFile(rawFile.getName(), "rw").getChannel();
out.writeContainer(fc);
fc.close();
Log.d(TAG, "Finished correcting raw video");
}
希望这能为您指明正确的方向!
关于video - Android : mp4 output file not fully playable 上没有预览的 Camera2 视频录制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37767511/
你能解释一下两者之间的区别吗 和 ? 最佳答案 通过使用 .您可以添加多个源元素。多个源元素可以链接到不同的视频文件。浏览器将使用第一个识别的格式。
我正在使用 ImagePickerController 处理 iPhone 视频捕获。我已经设置了图像选择器 Controller 的属性。我用它来将视频的最大长度设置为 60 秒。 imagePic
我正在制作一个进行基本视频处理的应用程序。我成功地合并到视频(视频上的视频)。 如何将左上角的小视频裁剪成一个圆圈? 最佳答案 如果您想导出该视频,您需要: 创建 CALayer,它将成为您的视频层的
我正在使用 SVT-AV1 和 FFMPEG 将视频编码为 AV1 视频和 opus 音频编解码器(.webm),它工作正常,除了视频搜索不起作用(非常糟糕)。当我寻找时,CPU 使用率会上升,并且需
在 Adobe Muse 中使用 VIDEO.JS 目前我已将海报图像配置为在视频开头显示, 当视频结束时,我希望海报图像重新出现。谢谢你的帮助! 最佳答案 将来最好的方法是通过 css。我只是a
我目前正在尝试从单张图片 (1980*1024) 生成视频 这是我的命令: ffmpeg -threads 8 -r 1 -loop 1 -i "C:\Library\Titling\__Resour
我想从 HTML 获取框架 javascript 中的组件,以便我可以处理它们然后输出到 Canvas 最佳答案 看看这个代码笔:Demo var videoId = 'video'; va
我已经使用 video.js 一段时间了,正在寻找响应式解决方案。我看到 4.6 声称是这样,但无法开始工作。我在文档中找不到任何关于使其响应的内容。我基本上只需要它保持在容器的 100% 并保持其纵
我正在寻找任何用于设置视频流服务器的现代资源。最好是开源解决方案。 我对此的搜索导致了很多死胡同。我也确实需要构建自己的服务而不是支付服务费用。 最佳答案 要设置您自己的视频流服务器,您应该从以下组件
如何在处理流媒体或网络视频时拦截“无法播放视频”对话框? 我尝试了以下操作并能够显示我的自定义错误消息。但最重要的是,我仍然收到 Android MediaPlayer 错误对话框“无法播放视频”。
它使我的视频居中并将控件放置在 div 底部但视频流出。在 css 样式表中,css 似乎无法识别。样式表中的 cos 颜色为黑色。我使用 Chrome 。 div.video_div{ width:
在 HTML5 video 元素中,您定义 type 属性的值始终以 video 开头。从元素是视频不是已经很明显,它是视频类型吗?为什么需要这样的视频:type="video/mp4",不应该只是t
我想通过 jQuery 或 Javascript 检测 html5 标签内的特定视频何时已完全加载(我的意思是,下载到浏览器的缓存中)。视频具有 preload = "auto"属性。 我尽我所能做到
HTML5 带来或将带来和 标签等等。自从我听说了他们,读了之后更是如此Why do we have an img element?特别是Jay C. Weber's message back fro
我正在制定一个 Web 应用程序的详细信息,该应用程序涉及顺序加载一长串(非常短的)视频剪辑,一个接一个,用户偶尔会输入建立新的视频剪辑加载方向. 我希望能够让浏览器一次预加载五个视频剪辑。然而,我们
我想知道 HTML5 标签现在支持.avi 格式视频文件的播放。 最佳答案 简短回答:否。改用 WebM 或 Ogg。 This article几乎涵盖了您需要了解的有关 的所有信息元素,包括哪些浏
尽管它似乎处于某种危险之中,但开放视频标准是一个好主意。我看到了一些关于运动跟踪的演示——只是概念验证,但仍然很有趣。现在,我要说的是,如果可以访问用户的网络摄像头,像这样的概念真的会是一个收获……想
我正在尝试使用 php-facebook-sdk 并借助 curl Facebook API 创建广告。 我已经使用 curl 上传了我的视频,它返回了一个 ID。现在,该视频 ID 将用于添加广告,
我正在使用 Video.js在我的网站上显示视频的插件。 我想删除画中画图标。我已经尝试了几个小时,但没有成功。 我做错了什么? 最佳答案 它应该是 data-setup='{"cont
使用 MediaRecorder 从 SurfaceView 录制视频 录音机 recorderProfile = CamcorderProfile.get( CamcorderProfile.QUA
我是一名优秀的程序员,十分优秀!