我正在从 iOS 上的 Unity 应用程序生成视频。我正在使用 iVidCap,它使用 AVFoundation 来执行此操作。那一侧一切正常。本质上,视频是通过使用纹理渲染目标并将帧传递给 Obj-C 插件来渲染的。
现在我需要向视频添加音频。音频将是在特定时间发生的声音效果,也可能是一些背景声音。所使用的文件实际上是 Unity 应用程序内部的资产。我可以将它们写入手机存储,然后生成 AVComposition,但我的计划是避免这种情况并将音频合成在浮点格式缓冲区中(从音频剪辑获取音频采用浮点格式)。稍后我可能会做一些动态音频效果。
几个小时后,我设法录制音频并与视频一起播放......但它很卡顿。
目前,我只是在视频的每帧持续时间内生成一个方波并将其写入 AVAssetWriterInput。稍后,我将生成我真正想要的音频。
如果我生成大量样本,我就不会出现卡顿的情况。如果我把它写成块(我更喜欢分配一个巨大的数组),那么音频块似乎会互相剪辑:

我似乎无法弄清楚这是为什么。我很确定我得到的音频缓冲区的时间戳是正确的,但也许我整个部分都做错了。或者我是否需要一些标志来使视频与音频同步?我看不出这是问题所在,因为将音频数据提取到 wav 后,我可以在波形编辑器中看到问题。
编写音频的相关代码:
- (id)init {
self = [super init];
if (self) {
// [snip]
rateDenominator = 44100;
rateMultiplier = rateDenominator / frameRate;
sample_position_ = 0;
audio_fmt_desc_ = nil;
int nchannels = 2;
AudioStreamBasicDescription audioFormat;
bzero(&audioFormat, sizeof(audioFormat));
audioFormat.mSampleRate = 44100;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = nchannels;
int bytes_per_sample = sizeof(float);
audioFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsAlignedHigh;
audioFormat.mBitsPerChannel = bytes_per_sample …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 AVAssetWriter 执行屏幕录制,它也接受音频输入。但是,我一直陷入这个错误,在appendSampleBuffer:(内部encodeAudioFrame:)进行几次调用后,AVAssetWriter有时会变成 AVAssetWriterStatusFailed
Failed: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x32b570 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x70d710 "The operation couldn\xe2\x80\x99t be completed. (OSStatus error -12737.)", NSLocalizedFailureReason=An unknown error occurred (-12737)}\nRun Code Online (Sandbox Code Playgroud)\n\n几点观察:
\n\n任何帮助将不胜感激。
\n\n下面是我正在使用的代码,为简洁起见,省略了几个部分。我目前使用的是 OSX 10.9 SDK,ARC 已关闭。
\n\n- (BOOL) startRecording\n{\n if (!isRecording)\n {\n dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\n [self startCapture];\n\n [self setUpWriter];\n\n startedAt = [NSDate date];\n isRecording …Run Code Online (Sandbox Code Playgroud) macos objective-c avfoundation avcapturesession avassetwriter
我正在尝试将 CMSampleBufferRefs 附加到 AVAssetWriterInput 并且我不断遇到错误崩溃:
[AVAssetWriterInput appendSampleBuffer:] status 为 0 时无法调用方法
代码:
在视图中加载
NSArray *cachePaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [cachePaths firstObject];
NSString *filename = @"test.mp4";
NSString *filePath = [cacheDirectory stringByAppendingPathComponent:filename];
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:filePath];
NSError *errors;
assetWriter = [[AVAssetWriter alloc] initWithURL:outputURL fileType:(NSString *)kUTTypeMPEG4 error:&errors];
videoWriteInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:outputSettings];
audioWriteInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:audioSettings];
[audioWriteInput addTrackAssociationWithTrackOfInput:videoWriteInput type:AVTrackAssociationTypeTimecode];
audioWriteInput.expectsMediaDataInRealTime = YES;
videoWriteInput.expectsMediaDataInRealTime = YES;
Run Code Online (Sandbox Code Playgroud)
记录功能
-(void)prepareVideo {
if (![assetWriter startWriting]) …Run Code Online (Sandbox Code Playgroud) 我有一个附加到 AVPlayerItem 的 AudioTapProcessor。static void tap_ProcessCallback(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut, CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut)
处理时会调用
。
我需要将其转换为AudioBufferList,CMSampleBuffer以便将其AVAssetWriterAudioInput.appendSampleBuffer写入电影文件。
那么如何转换AudioBufferList为CMSampleBuffer?我试过了,但得到 -12731 错误:错误 cCMSampleBufferSetDataBufferFromAudioBufferList :Optional("-12731")
func processAudioData(audioData: UnsafeMutablePointer<AudioBufferList>, framesNumber: UInt32) {
var sbuf : Unmanaged<CMSampleBuffer>?
var status : OSStatus?
var format: Unmanaged<CMFormatDescription>?
var formatId = UInt32(kAudioFormatLinearPCM)
var formatFlags = UInt32( kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked )
var audioFormat = AudioStreamBasicDescription(mSampleRate: 44100.00, mFormatID:formatId, mFormatFlags:formatFlags , mBytesPerPacket: 1, mFramesPerPacket: 1, mBytesPerFrame: 16, mChannelsPerFrame: …Run Code Online (Sandbox Code Playgroud) 标题说明了这一点,在开始编码视频并出现错误之前,我想知道每个设备的最大分辨率。我在想是否有类似 AVCaptureDevicesupportsAVCaptureSessionPreset: .. 但对于使用 AVAssetWriter 的常规编码。
问候,感谢您的帮助。
我正在使用 AVFoundationAVCaptureSession捕获视频以进行实时流传输(使用 发送到服务器RTMP protocol)。
的回调委托方法AVCaptureVideoDataOutputSampleBufferDelegate并AVCaptureAudioDataOutputSampleBufferDelegate返回CMSampleBufferRef以下方法:
- (void)captureOutput:(AVCaptureOutput *)captureOutputdidOutputSampleBuffer:(CMSampleBufferRef)sampleBufferfromConnection:(AVCaptureConnection *)connection\nRun Code Online (Sandbox Code Playgroud)\n根据此链接的内容,我可以使用此链接将此缓冲区内容转换为文件。
\n喜欢
\nNSURL *url = \xe2\x80\xa6;\nAVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeMPEG4 error:nil];\nAVAssetWriterInput *videoInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:nil];\nvideoInput.expectsMediaDataInRealTime = YES;\nAVAssetWriterInput *audioInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:nil];\naudioInput.expectsMediaDataInRealTime = YES;\nif ([assetWriter canAddInput:videoInput]) {\n [assetWriter addInput:videoInput];\n}\nif ([assetWriter canAddInput:audioInput]) {\n [assetWriter addInput:audioInput];\n}\nRun Code Online (Sandbox Code Playgroud)\n但我没有得到此文件转换所涉及的确切逻辑。这didOutputSampleBuffer是一帧一帧捕获(未压缩)的原始数据,我想以一定的间隔将这些帧转换为单个文件。比如每 10 秒左右一次。我想将此文件发送到服务器。
有人可以简要介绍一下如何AVAssetWriter工作吗?或者如果我做错了什么可以纠正我。
将图像叠加添加到使用AVAssetWriter创建的视频的正确方法是什么?
使用AVAssetExportSession可以这样做,但是这个问题是关于如何使用AVAssetWriter这样做,因此可以更好地控制质量和输出.
有两种情况:
1)简单:添加在视频的整个持续时间内出现的单个叠加层(类似于水印).
2)复杂:添加不同的叠加层,在不同时间为视频设置动画效果(类似于使用AVVideoCompositionCoreAnimationTool).
我正在制作一个利用 AVFoundation 录制视频的示例应用程序。重点是让我可以更好地控制视频的录制方式。在我的示例项目中,我有视频捕获,但正在努力正确处理方向。
我在网上做了很多搜索,发现其他人建议我不应该允许我的捕获视图或捕获会话根据方向旋转,而是设置转换以在播放期间旋转视频。我在 iOS 和 Mac 设备上运行良好,但我想知道我是否会在其他平台(如 Windows 或 Android)上遇到问题。
此外,当我查看录制视频的元数据时,我发现宽度和高度没有正确设置为方向。这是有道理的,因为我只是在转换视频的呈现方式,而不是它的实际分辨率。
我的问题是如何正确支持纵向和横向并在视频文件输出中正确反映?我需要这些视频在所有平台上都能正确播放,所以我认为分辨率很重要。
以下是我迄今为止所写的完整来源。我很感激你们能提供的任何建议。
import UIKit
import AVFoundation
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate {
//MARK: - Outlet
@IBOutlet weak var previewView: UIView!
@IBOutlet var playStopButton: UIButton!
//MARK: - Private Variables
let videoQueue = DispatchQueue(label: "VideoQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .workItem, target: nil)
private let captureSession = AVCaptureSession()
var outputUrl: URL {
get {
if let url = _outputUrl {
return url
}
_outputUrl = outputDirectory.appendingPathComponent("video.mp4")
return _outputUrl!
}
} …Run Code Online (Sandbox Code Playgroud) 我正在使用 AVAssetWriter 压缩视频。如果我将视频压缩文件设置为 Quicktime 电影,它工作正常,但是我想将其导出为 MPEG4,但在运行时出现此错误:
为了执行到文件类型 public.mpeg-4 的传递,请在 AVAssetWriterInput 初始值设定项中提供格式提示
这是我声明文件类型的具体代码:
let videoInputQueue = DispatchQueue(label: "videoQueue")
let audioInputQueue = DispatchQueue(label: "audioQueue")
let formatter = DateFormatter()
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
let date = Date()
let documentsPath = NSTemporaryDirectory()
let outputPath = "\(documentsPath)/\(formatter.string(from: date)).mp4"
let newOutputUrl = URL(fileURLWithPath: outputPath)
do{
assetWriter = try AVAssetWriter(outputURL: newOutputUrl, fileType: AVFileTypeMPEG4)
}catch{
assetWriter = nil
}
guard let writer = assetWriter else{
fatalError("assetWriter was nil")
}
writer.shouldOptimizeForNetworkUse = true
writer.add(videoInput)
writer.add(audioInput)
Run Code Online (Sandbox Code Playgroud)
这是我的压缩的完整代码:
func compressFile(urlToCompress: URL, completion:@escaping …Run Code Online (Sandbox Code Playgroud) 我正在通过 iPhone 摄像头录制经过过滤的视频,在录制时将 CIImage 实时转换为 UIImage 时,CPU 使用率大幅增加。我制作 CVPixelBuffer 的缓冲区函数使用了 UIImage,到目前为止,它需要我进行此转换。如果可能的话,我想创建一个采用 CIImage 的缓冲函数,这样我就可以跳过从 UIImage 到 CIImage 的转换。我认为这会给我录制视频时的性能带来巨大的提升,因为 CPU 和 GPU 之间不会有任何交接。
这就是我现在所拥有的。在我的 captureOutput 函数中,我从 CIImage 创建了一个 UIImage,它是过滤后的图像。我使用 UIImage 从缓冲区函数创建一个 CVPixelBuffer,并将其附加到 assetWriter 的 pixelBufferInput:
let imageUI = UIImage(ciImage: ciImage)
let filteredBuffer:CVPixelBuffer? = buffer(from: imageUI)
let success = self.assetWriterPixelBufferInput?.append(filteredBuffer!, withPresentationTime: self.currentSampleTime!)
Run Code Online (Sandbox Code Playgroud)
我使用 UIImage 的缓冲函数:
func buffer(from image: UIImage) -> CVPixelBuffer? {
let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
var pixelBuffer : CVPixelBuffer?
let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(image.size.width), Int(image.size.height), kCVPixelFormatType_32ARGB, attrs, …Run Code Online (Sandbox Code Playgroud) avassetwriter ×10
ios ×7
avfoundation ×5
iphone ×3
objective-c ×3
swift ×3
video ×2
ciimage ×1
core-audio ×1
macos ×1
recorder ×1
uiimage ×1
xcode ×1