使用 AVCaptureSession 和 AVAssetWriter 翻转相机时无缝录音

2023-12-01

我正在寻找一种在前后摄像头之间切换时保持无缝音轨的方法。市场上的许多应用程序都可以做到这一点,一个例子是 SnapChat……

解决方案应使用 AVCaptureSession 和 AVAssetWriter。此外,它不应该明确使用 AVMutableComposition,因为有一个bugAVMutableComposition 和 AVCaptureSession ATM 之间。另外,我负担不起后期处理时间。

目前,当我更改视频输入时,音频录制会跳过并变得不同步。

我添加了可能相关的代码。

翻转相机

-(void) updateCameraDirection:(CamDirection)vCameraDirection {
    if(session) {
        AVCaptureDeviceInput* currentInput;
        AVCaptureDeviceInput* newInput;
        BOOL videoMirrored = NO;
        switch (vCameraDirection) {
            case CamDirection_Front:
                currentInput = input_Back;
                newInput = input_Front;
                videoMirrored = NO;
                break;
            case CamDirection_Back:
                currentInput = input_Front;
                newInput = input_Back;
                videoMirrored = YES;
                break;
            default:
                break;
        }

        [session beginConfiguration];
        //disconnect old input
        [session removeInput:currentInput];
        //connect new input
        [session addInput:newInput];
        //get new data connection and config
        dataOutputVideoConnection = [dataOutputVideo connectionWithMediaType:AVMediaTypeVideo];
        dataOutputVideoConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
        dataOutputVideoConnection.videoMirrored = videoMirrored;
        //finish
        [session commitConfiguration];
    }
}

样品缓冲液

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    //not active
    if(!recordingVideo)
        return;

    //start session if not started
    if(!startedSession) {
        startedSession = YES;
        [assetWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
    }

    //Process sample buffers
    if (connection == dataOutputAudioConnection) {
        if([assetWriterInputAudio isReadyForMoreMediaData]) {
            BOOL success = [assetWriterInputAudio appendSampleBuffer:sampleBuffer];
            //…
        }

    } else if (connection == dataOutputVideoConnection) {
        if([assetWriterInputVideo isReadyForMoreMediaData]) {        
            BOOL success = [assetWriterInputVideo appendSampleBuffer:sampleBuffer];
            //…
        }
    }
}

也许调整音频采样时间戳?


嘿,我面临着同样的问题,发现切换相机后下一帧被推得很远。这似乎会改变之后的每一帧,从而导致视频和音频不同步。我的解决方案是在切换相机后将每个错位的帧移动到正确的位置。

抱歉,我的答案将在 Swift 4.2 中

你必须使用AVAssetWriterInputPixelBufferAdaptor为了在指定的呈现时间戳处附加示例缓冲区。

previousPresentationTimeStamp是前一帧的呈现时间戳,currentPresentationTimestamp正如您所猜测的当前的呈现时间戳。maxFrameDistance测试时效果很好,但您可以根据自己的喜好进行更改。

let currentFramePosition = (Double(self.frameRate) * Double(currentPresentationTimestamp.value)) / Double(currentPresentationTimestamp.timescale)
let previousFramePosition = (Double(self.frameRate) * Double(previousPresentationTimeStamp.value)) / Double(previousPresentationTimeStamp.timescale)
var presentationTimeStamp = currentPresentationTimestamp
let maxFrameDistance = 1.1
let frameDistance = currentFramePosition - previousFramePosition
if frameDistance > maxFrameDistance {
    let expectedFramePosition = previousFramePosition + 1.0
    //print("[mwCamera]: Frame at incorrect position moving from \(currentFramePosition) to \(expectedFramePosition)")

    let newFramePosition = ((expectedFramePosition) * Double(currentPresentationTimestamp.timescale)) / Double(self.frameRate)

    let newPresentationTimeStamp = CMTime.init(value: CMTimeValue(newFramePosition), timescale: currentPresentationTimestamp.timescale)

    presentationTimeStamp = newPresentationTimeStamp
}

let success = assetWriterInputPixelBufferAdator.append(pixelBuffer, withPresentationTime: presentationTimeStamp)
if !success, let error = assetWriter.error {
    fatalError(error.localizedDescription)
}

另请注意- 这之所以有效,是因为我保持了帧速率一致,因此请确保您在整个过程中完全控制捕获设备的帧速率。

我这里有一个使用这个逻辑的仓库

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 AVCaptureSession 和 AVAssetWriter 翻转相机时无缝录音 的相关文章

  • CLGeocoder reverseGeocodeLocation 返回“kCLErrorDomain 错误 9”

    我正在根据本文开发具有反向地理编码功能的 iOS 应用程序 地理编码教程 http jonathanfield me jons blog clgeocoder example html 但是当我在模拟器上进行这样的测试时 我收到 kCLEr
  • UIButton 和滑动手势

    我有一个UIView有两个UIButton每侧 左侧和右侧 都有 s 和UIImageView在中心 点击任一按钮都会改变UIImageView那行得通 我想要滑动的能力UIView以及它改变UIImageView 现在 您必须在UIIma
  • 动态图标 iOS [重复]

    这个问题在这里已经有答案了 可能的重复 每天更改图标 https stackoverflow com questions 4038305 changing icon per day 如何制作动态图标 例如在日历中 每天该数字都会更改为当前值
  • 按钮操作在 iPhone 中不起作用?

    我有一个 iPhone 应用程序 我在其中添加一个自定义视图 尽管有一个导航栏视图 在正常情况下 我隐藏该自定义视图 并在需要时取消隐藏它 现在 我正在向该自定义视图添加一个具有操作的按钮 但是当我点击它时 没有任何操作起作用 任何人都可以
  • iOS UIView子类,将透明文本绘制到背景

    我想将文本绘制到 UIView 上的子类上 以便文本从形状中切出 并且视图后面的背景显示出来 就像在 OSX Mavericks 徽标中找到的那样here http www n3rdabl3 co uk wp content uploads
  • 图像高斯模糊 - iOS 8

    我有一个移动的背景图像 我想模糊它的底部 我would只用 Photoshop 就能做到 但由于图像会移动 效果不太好 这就是我的意思 看图片底部 基本上就像底座对 iPhone 的影响一样 我使用的是 iOS 8 但不是 Swift 我根
  • NSData 不接受有效的 base64 编码字符串

    我正在 iOS 7 客户端实现 JSON Web Token 身份验证 效果很好 我的应用程序接收令牌 并可以使用它们对我的服务器进行经过身份验证的调用 现在 我希望我的客户端代码检查令牌的过期日期 以便它知道何时重新进行身份验证 检查 J
  • UITableView 最后一个单元格被 UITabBarController 隐藏

    我面临一个奇怪的问题 我有一个UITableView在最初的UIViewController of the UITabBarController 起初一切都很好 但是当我更改选项卡并返回到第一个选项卡时 最后一个单元格UITableView
  • 如何通过填充 NSDictionary 以 JSON 格式发送 UIImage

    我正在尝试使用 JSON 将数据发送到服务器 我可以使用我的对象和关键参数创建 NSDictionary 但我想发送我的图片 图片是UIImage NSDictionary mainJSON NSDictionary dictionaryW
  • 如何获取核心数据中现有实体(表)的列表

    如何获取核心数据中特定模式 托管对象模型 的现有实体 表 列表 我刚刚开始实施核心数据概念并坚持这些要点 就像是 SELECT COUNT FROM information schema tables WHERE table schema
  • 什么是已弃用的推送转场? (iOS 8)[重复]

    这个问题在这里已经有答案了 我不知道在这种情况下已弃用意味着什么 我是编程新手 正在 Xcode 6 中制作我的前几个应用程序 今天我正在制作一个待办事项列表应用程序 当连接到用户可以输入新待办事项以添加到主表的场景时 我被邀请使用推送转场
  • iOS:如何在不降低 fps 的情况下播放音频?

    我正在使用 Sprite Kit 最好使用 Swift 库 为 iOS 9 开发游戏 目前 我正在使用 Singleton 在其中预加载音频文件 每个文件都连接到一个单独的 AVAudioPlayer 实例 这是一个简短的代码片段来了解这个
  • 使用 UItableviewCell 实现 Google 地图

    我正在尝试在 UItableviewCell 组件内实现谷歌地图 我这样做的方法是在原型单元中定义 GMSMapView 然后使用 dequeueReusableCell 方法配置地图单元 但是 我尝试应用的任何更改都会失败 例如添加标记
  • 无法验证包:721772200.itmsp

    我写这篇文章是因为我有一个严重的问题 我在cartoonsmart 网站上购买了Commander Cool 游戏 然而 一个严重的问题发生了 iTune Connect 验证无法接受该申请 我尝试从两个不同的开发者帐户发布它 但错误仍然发
  • Swift 3:如何访问48字节CFData中matrix_float3x3的值?

    我正在尝试访问内在矩阵answer https stackoverflow com a 48159895 9296667 通过运行下面的命令 我能够得到一个 48 字节的任意对象 https developer apple com docu
  • NSCFData isRessized 崩溃?

    我目前在控制台中收到此崩溃日志 2011 08 23 19 18 40 064 App 1697 707 NSCFData isResizable unrecognized selector sent to instance 0x11f1c
  • 使用 Protobuf-net,我收到有关 List 未知线路类型的异常

    我已经开始将 Unity iOS 游戏转换为使用 Protobuf net 保存状态 看起来一切正常 直到我将此实例变量添加到GameState ProtoMember 10 public List
  • 如何在 Swift 中使用indexesOfObjectsPassingTest:

    IndexOfObjectsPassingTest 的声明在 Swift 中看起来像这样 func indexesOfObjectsPassingTest predicate AnyObject Int CMutablePointer
  • Admob 广告无法快速显示

    您好 我正在尝试将 admob 广告添加到已使用 swift 上传到应用商店的应用程序中 我在 admob 中制作了一个应用程序并复制了 appid 和广告 id 并显示了各自的横幅广告和插页式广告 这里的问题是当我写这行时 request
  • 如何正确创建迦太基 cartfile?

    我正在研究购物车文件 迫不及待地想 简单地创建一个购物车文件 就像所有说明所说的那样 只是 如何 简单地 创建一个 Cartfile 我创建了一个纯文本文档 将其命名为 cartfile 并在其中复制了一些依赖项 Ran carthage

随机推荐

  • 将电话号码与国家/地区代码相匹配的正则表达式

    这是我用来匹配电话号码的正则表达式 例如 00 00 00 00 00 00 00 0 00 00 00 00 00 0 00 00 00 00 d 2 s d 2 s d 2 s d 2 s d 2 s d 2 s d 2 s d s d
  • 如何在 Symfony 中设置数据转换器以重用现有实体?

    我正在 Symfony 中开发一个具有内置标记功能的文章编辑器 控制器 class MainController extends Controller public function indexAction Request request
  • getGraphics和paintComponent的Graphics对象之间的区别

    如果我使用 JPanel getGraphics 返回的 Graphics 对象与在 PaintComponent 方法中传递的 Graphics 对象有什么区别 getGraphics Can be null 是最后一次喷漆过程的 快照
  • .NET 中的托管和非托管代码

    就 NET 框架而言 托管代码和非托管代码有什么区别 托管代码是一种差异化 由 Microsoft 创建来识别 需要的代码 并且只会在以下条件下执行 管理 一个CLR 虚拟机 导致Bytecode 使用托管代码的好处包括 程序员的便利性 通
  • 用 numpy 最小二乘法拟合线性曲面

    所以我想解方程z a b y c x 得到a b c 即 使 平面 表面适合 3D 空间中的大量散点 但我似乎找不到任何东西 我认为会有一个简单的模块来解决这样一个简单的问题 我试过了 其中x y z是数组 ys zip x y coeff
  • 我可以通过java在我的系统上安装证书吗

    我可以通过java在我的系统上安装证书吗 像这样的东西例如 证书 证书 someClass getsystemCertificates 有没有可用的api 您可以使用keytool命令获取 cacerts 文件中的证书列表 该文件是 Jav
  • 使用较短的数组查询 IndexedDB 复合索引

    IndexedDB 允许您对多个属性创建索引 就像如果你有类似的物体 a 0 b 0 你可以建立索引a and b 复合索引的行为是很奇怪 但显然应该可以使用比复合索引短的数组进行查询 所以在我的示例中 我应该能够查询类似的内容 0 并得到
  • Django登录AttributeError:'AnonymousUser'对象没有属性'_meta'

    我有这个代码 from django contrib auth import logout login authenticate if User objects filter email email exists existing user
  • 更新时如何检查 Tensorflow 中梯度的 NaN?

    All 当您训练具有大量样本的大型模型时 某些样本在参数更新时可能会导致 NaN 梯度 我想找出这些样本 同时我不希望这批样本的梯度更新模型的参数 因为这可能会导致模型的参数为NaN 那么有人有解决这个问题的好主意吗 我的代码如下 Crea
  • 隐式删除默认构造函数与编译器不合成默认构造函数相同

    我正在学习 C 中的类 我才知道在某些情况可以隐式删除默认构造函数 另外 我读到 当我们有用户定义的构造函数时 编译器将不会自动合成默认构造函数 以我目前的理解 隐式删除默认构造函数与默认构造函数不自动合成时的情况有很大不同 我的意思是 在
  • 如果这个类没有 Dispose 方法,它如何实现 IDisposable?

    FtpWeb响应实现 IDisposable 但它没有 Dispose 方法 这怎么可能 它在基类WebResponse中实现 参见http msdn microsoft com en us library system net webre
  • 用于检查输入是否为整数的 C++ 修复[重复]

    这个问题在这里已经有答案了 例如 如果我输入 2a 它不会显示错误 也不会要求用户重新输入该值 我该如何解决 while std cin fail std cout lt lt ERROR enter a number lt lt std
  • 如何使用Guice的@Singleton?

    我需要创建某个类的一个实例 并且这个实例需要可以从代码中的任何位置访问 所以 我找到了 Guice 并且我想使用这个包中的 Singleton 但我没有找到任何示例或一些文档来说明如何使用它以及如何进行声明 Singleton 非常容易使用
  • Addhandler、button.click 未使用 VB.NET 触发

    我遇到了按钮和 AddHandler 的问题 仅当我在 Page load 中使用 AddHandler Button1 click AddressOf 时它才有效 但如果我在子例程之一中动态创建按钮 则该事件不会触发 例如
  • 在大图像中绘制边界框

    我有一个大的二值图像 4k x 7k 像素 我想从中提取整个黄色部分作为单个矩形 我尝试了二元腐蚀来均匀黄色区域内的特征 然后我用了bbox的方法skimage regionprops但对于带有一个大 bbox 的大图像来说 它似乎工作得不
  • 在 html 中创建不可见的文本字段?

    我正在尝试将 html 代码放入我老板提供的设计模型中 并且一些美学 例如搜索栏的形状 有点奇怪和复杂 作为一个简单的解决方案 我想我只需将一个文本字段放在搜索栏的图像上 但我无法让它工作 谁能建议一种方法 将文本字段分层在图像上 使其不可
  • R:根据嵌套组计算比例

    我正在使用 R 编程语言 我有以下数据集 set seed 123 library dplyr Patient ID 1 5000 gender lt c Male Female gender lt sample gender 5000 r
  • 尝试使用 PDO 更新记录

    我更新了问题代码 但仍然有问题 没有错误 但没有更新记录 还需要弄清楚如何写入记录 更新成功 我被困在这个更新页面了
  • 无法打开数据库-Android

    我正在使用 SQL 开发一个简单的 Android 应用程序 我遵循以下指南 http www reigndesign com blog using your own sqlite database in android applicati
  • 使用 AVCaptureSession 和 AVAssetWriter 翻转相机时无缝录音

    我正在寻找一种在前后摄像头之间切换时保持无缝音轨的方法 市场上的许多应用程序都可以做到这一点 一个例子是 SnapChat 解决方案应使用 AVCaptureSession 和 AVAssetWriter 此外 它不应该明确使用 AVMut