Swift 4 - 在 mac os 上使用 AVAssetWriter 进行 avfoundation 屏幕和音频录制 - 视频冻结

2023-12-20

我正在使用 Aperture 从屏幕录制音频和视频。我们需要降低视频的比特率,所以我尝试重写它并使用 AVAssetWriter 录制视频。我的实现基于 CustomCamera 项目,并且几乎可以工作。问题出在视频中,几秒钟后它就冻结了,尽管音频正常。请问你能帮帮我吗?我不知道问题出在哪里,也许是缓冲区或垃圾收集器收集一些变量的问题。谢谢。

这是代码:

//
//  ViewController.swift
//  CustomCamera
//
//  Created by Taras Chernyshenko on 6/27/17.
//  Copyright © 2017 Taras Chernyshenko. All rights reserved.
//
import AVFoundation
import Photos

class NewRecorder: NSObject,
  AVCaptureAudioDataOutputSampleBufferDelegate,
AVCaptureVideoDataOutputSampleBufferDelegate {

  private var session: AVCaptureSession = AVCaptureSession()
  private var deviceInput: AVCaptureScreenInput?
  private var previewLayer: AVCaptureVideoPreviewLayer?
  private var videoOutput: AVCaptureVideoDataOutput = AVCaptureVideoDataOutput()
  private var audioOutput: AVCaptureAudioDataOutput = AVCaptureAudioDataOutput()

  //private var videoDevice: AVCaptureDevice = AVCaptureScreenInput(displayID: 69731840) //AVCaptureDevice.default(for: AVMediaType.video)!
  private var audioConnection: AVCaptureConnection?
  private var videoConnection: AVCaptureConnection?

  private var assetWriter: AVAssetWriter?
  private var audioInput: AVAssetWriterInput?
  private var videoInput: AVAssetWriterInput?

  private var fileManager: FileManager = FileManager()
  private var recordingURL: URL?

  private var isCameraRecording: Bool = false
  private var isRecordingSessionStarted: Bool = false

  private var recordingQueue = DispatchQueue(label: "recording.queue")


  func setup() {
    self.session.sessionPreset = AVCaptureSession.Preset.high

    self.recordingURL = URL(fileURLWithPath: "\(NSTemporaryDirectory() as String)/file.mp4")
    if self.fileManager.isDeletableFile(atPath: self.recordingURL!.path) {
      _ = try? self.fileManager.removeItem(atPath: self.recordingURL!.path)
    }

    self.assetWriter = try? AVAssetWriter(outputURL: self.recordingURL!,
                                          fileType: AVFileType.mp4)
    self.assetWriter!.movieFragmentInterval = kCMTimeInvalid
    self.assetWriter!.shouldOptimizeForNetworkUse = true

    let audioSettings = [
      AVFormatIDKey : kAudioFormatMPEG4AAC,
      AVNumberOfChannelsKey : 2,
      AVSampleRateKey : 44100.0,
      AVEncoderBitRateKey: 192000
      ] as [String : Any]

    let videoSettings = [
      AVVideoCodecKey : AVVideoCodecType.h264,
      AVVideoWidthKey : 1920,
      AVVideoHeightKey : 1080
      /*AVVideoCompressionPropertiesKey: [
        AVVideoAverageBitRateKey:  NSNumber(value: 5000000)
      ]*/
      ] as [String : Any]

    self.videoInput = AVAssetWriterInput(mediaType: AVMediaType.video,
                                         outputSettings: videoSettings)
    self.audioInput = AVAssetWriterInput(mediaType: AVMediaType.audio,
                                         outputSettings: audioSettings)

    self.videoInput?.expectsMediaDataInRealTime = true
    self.audioInput?.expectsMediaDataInRealTime = true

    if self.assetWriter!.canAdd(self.videoInput!) {
      self.assetWriter?.add(self.videoInput!)
    }

    if self.assetWriter!.canAdd(self.audioInput!) {
      self.assetWriter?.add(self.audioInput!)
    }

    //self.deviceInput = try? AVCaptureDeviceInput(device: self.videoDevice)
    self.deviceInput = AVCaptureScreenInput(displayID: 724042646)
    self.deviceInput!.minFrameDuration = CMTimeMake(1, Int32(30))
    self.deviceInput!.capturesCursor = true
    self.deviceInput!.capturesMouseClicks = true

    if self.session.canAddInput(self.deviceInput!) {
      self.session.addInput(self.deviceInput!)
    }

    self.previewLayer = AVCaptureVideoPreviewLayer(session: self.session)

    //importent line of code what will did a trick
    //self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill

    //let rootLayer = self.view.layer
    //rootLayer.masksToBounds = true
    //self.previewLayer?.frame = CGRect(x: 0, y: 0, width: 1920, height: 1080)

    //rootLayer.insertSublayer(self.previewLayer!, at: 0)

    self.session.startRunning()

    DispatchQueue.main.async {
      self.session.beginConfiguration()

      if self.session.canAddOutput(self.videoOutput) {
        self.session.addOutput(self.videoOutput)
      }

      self.videoConnection = self.videoOutput.connection(with: AVMediaType.video)
      /*if self.videoConnection?.isVideoStabilizationSupported == true {
        self.videoConnection?.preferredVideoStabilizationMode = .auto
      }*/
      self.session.commitConfiguration()

      let audioDevice = AVCaptureDevice.default(for: AVMediaType.audio)
      let audioIn = try? AVCaptureDeviceInput(device: audioDevice!)

      if self.session.canAddInput(audioIn!) {
        self.session.addInput(audioIn!)
      }

      if self.session.canAddOutput(self.audioOutput) {
        self.session.addOutput(self.audioOutput)
      }

      self.audioConnection = self.audioOutput.connection(with: AVMediaType.audio)
    }
  }

  func startRecording() {
    if self.assetWriter?.startWriting() != true {
      print("error: \(self.assetWriter?.error.debugDescription ?? "")")
    }

    self.videoOutput.setSampleBufferDelegate(self, queue: self.recordingQueue)
    self.audioOutput.setSampleBufferDelegate(self, queue: self.recordingQueue)
  }

  func stopRecording() {
    self.videoOutput.setSampleBufferDelegate(nil, queue: nil)
    self.audioOutput.setSampleBufferDelegate(nil, queue: nil)

    self.assetWriter?.finishWriting {
      print("Saved in folder \(self.recordingURL!)")
      exit(0)
    }
  }
  func captureOutput(_ captureOutput: AVCaptureOutput, didOutput
    sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {

    if !self.isRecordingSessionStarted {
      let presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
      self.assetWriter?.startSession(atSourceTime: presentationTime)
      self.isRecordingSessionStarted = true
    }

    let description = CMSampleBufferGetFormatDescription(sampleBuffer)!

    if CMFormatDescriptionGetMediaType(description) == kCMMediaType_Audio {
      if self.audioInput!.isReadyForMoreMediaData {
        //print("appendSampleBuffer audio");
        self.audioInput?.append(sampleBuffer)
      }
    } else {
      if self.videoInput!.isReadyForMoreMediaData {
        //print("appendSampleBuffer video");
        if !self.videoInput!.append(sampleBuffer) {
          print("Error writing video buffer");
        }
      }
    }
  }
}

所以我通过移动这段代码来修复它

if self.session.canAddInput(self.deviceInput!) {
  self.session.addInput(self.deviceInput!)
}

调用 self.session.beginConfiguration() 之后,所以

self.session.beginConfiguration()
  if self.session.canAddInput(self.deviceInput!) {
    self.session.addInput(self.deviceInput!)
  }

  if self.session.canAddOutput(self.videoOutput) {
    self.session.addOutput(self.videoOutput)
  }

  self.videoConnection = self.videoOutput.connection(with: AVMediaType.video)

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

Swift 4 - 在 mac os 上使用 AVAssetWriter 进行 avfoundation 屏幕和音频录制 - 视频冻结 的相关文章

  • 未捕获的 Kotlin 异常:kotlin.native.In CorrectDereferenceException:非法尝试访问非共享

    我尝试使用 Kotlin MPP Multiplatform 开发 Android 和 iOS 之间的共享库 但我面临着 iOS 中线程的问题 对于我在 iOS 中的应用程序 我在主线程中建立了对象 但它可能调用其他线程中的函数并抛出此异常
  • 在 iOS 上使用 HEVC 编码器输出视频尺寸巨大

    我有一个项目 目前使用 H 264 编码器在 iOS 上录制视频 我想尝试在 iOS 11 中使用新的 HEVC 编码器来减小文件大小 但发现使用 HEVC 编码器会导致文件大小急剧膨胀 GitHub 上的一个项目显示了该问题 它使用 H
  • skView.ignoreSiblingOrder 在 swift 中的重要性/效率?

    这样做有多重要 高效skView ignoreSiblingOrder true初始化场景时 现在 我将其设置为 true 但由于某种原因 当我从 MainMenu 场景启动 GameScene 时 它 会在我的角色之前加载背景 即使背景的
  • 在 OSX 和 GNU 中使用“find”删除带有数字的文件名

    我正在尝试搜索一个文件并删除名称中包含数字的类似文件 我的文件 txt from myfile 00 04 version txt myfile 00 txt find E iregex myfile 0 9 1 txt 删除 myfile
  • 使用 mono/nunit-console/4 在 Mac OS X 控制台上运行测试

    我安装了 Max OS X 10 11 1 上面装有 Xamarin 我编写了简单的测试类 只是为了测试在 Mac OS X 和 Ubuntu 上运行 Nunit 测试 该类实际上有一个返回字符串的方法 using System names
  • 如何从 Firebase 同步检索数据?

    我有两个集合 即用户和问题 根据使用 userId 登录的用户 我检索currQuestion价值来自users收藏 基于currQuestion值 我需要检索question来自 Firebase 的文档Questions收藏 我使用下面
  • CustomNSError 协议有什么作用以及为什么我应该采用它?

    什么是CustomNSError协议的用途以及为什么我应该采用它 Apple提供的文档仅指出 描述错误类型 具体提供域 代码和 用户信息字典 我已经在谷歌上搜索过 但找不到与我的问题相关的任何内容 每种类型都符合Error协议是隐含地桥接的
  • 如何在 Swift 中创建 UIAlertView?

    我一直在努力在 Swift 中创建 UIAlertView 但由于某种原因我无法得到正确的语句 因为我收到此错误 找不到接受提供的 init 重载 论点 我是这样写的 let button2Alert UIAlertView UIAlert
  • 来自索引范围 Swift 的新数组

    我怎样才能做这样的事情 从数组中取出前 n 个元素 newNumbers numbers 0 n 目前出现以下错误 error could not find an overload for subscript that accepts th
  • 如何从 Mac OS X 中完全删除 Eclipse(包括设置和插件)?

    我的 Eclipse 与 GAE 损坏并且工作异常 所以我从Application文件夹中删除了Eclipse 但是留下了垃圾 我重新下载了全新的 eclipse 但它以旧设置运行 并且损坏的 GAE 结构仍然存在 如何从 Mac 上完全删
  • 适用于 C/C++ 和 Java 的 Eclipse IDE

    我正在尝试在运行 El Capitan 的 Mac 上设置 Java IDE 但是我找到的安装程序要求我为 C C 和 Java 安装单独的 IDE Eclipse Neon Eclipse 有什么选项可以让我拥有一个支持多种语言的 IDE
  • 从 Java 执行 .app 文件夹?

    有没有一种合理的方法可以直接从 Java 执行 app 目录 而不是深入查找二进制文件 我有一个带有一些首选项的应用程序 其中包括用于打开各种内容的外部程序 如果在 OSX 上用户可以只选择 app 文件夹 那就太好了 我可以查找 app
  • 在 Mac OS X 上构建 Linux 内核

    我正在做一个修改Linux内核的项目 我有一台桌面 Linux 机器 在上面构建内核没有问题 不过 我要去旅行 我想在途中工作 我只有一台 MacBook 当我尝试构建 Linux 内核时 它抱怨说elf h was not found 我
  • NSURLCache 不缓存

    我正在使用 Xcode 6 1 6A1030 iOS7 和 iOS8 模拟器 NSURLCache 似乎没有缓存任何东西 我使用 Cache Control 标头 我的服务器返回带有 max age 6000 的 Cache Control
  • 如何将CIFilter应用到UIView上?

    根据Apple docs 过滤属性CALayer不支持iOS 当我使用正在申请的应用程序之一时CIFilter to UIView即 Splice Funimate 和 Artisto 的视频编辑器 Videoshow FX 这意味着我们可
  • Swift:协议、结构、类

    我开始学习 Swift 语言 但在理解协议 结构和类方面遇到了困难 我来自 Android 方面的编程 所以我相信 Swift 协议基本上是 Java 接口 其中每一个的正确用例是什么 这些类比并不 完全 正确 但这就是我所理解的要点 是的
  • 在 Swift 中以编程方式为 iOS 制作带有名字首字母的图像,例如 Gmail

    我需要在 UITableView 中显示与其姓名相对应的每个用户的个人资料图片 在下载图像之前 我需要显示一张带有他名字的第一个字母的图像 就像在 GMail 应用程序中一样 如何在 Swift for iOS 中以编程方式执行此操作 不需
  • java setFullScreenWindow 在 Mac 中隐藏登录对话框

    我使用的是全屏窗口 类似于屏幕保护程序 使用这里的方法 GraphicsEnvironment getLocalGraphicsEnvironment getDefaultScreenDevice setFullScreenWindow t
  • 领域:结果 和列表

    是否可以转换Results
  • 如何观察UserDefaults的变化?

    我有一个 ObservedObject在我看来 struct HomeView View ObservedObject var station Station var body some View Text self station sta

随机推荐

  • 如何在 ANSI C 的结构中使用枚举?

    下面的代码必须在主函数中使用 但我不知道它是如何使用的 struct SomeItem enum MOVIE MUSIC itemType union struct Movie movie struct Music music 该结构用于带
  • Highchart js 最多可绘制 15 个图

    我在 Highchart js 中进行了很多尝试 但仍然找不到减少系列中元素数量的方法 如果我获得超过 15 天的数据 我必须将其减少并以 15 天的数据形式向用户显示 以便用户可以在不拥挤的情况下查看数据 该系列最多有 90 天 我必须减
  • IntelliJ IDEA 仅运行/调试一个文件

    我在 IntelliJ IDEA 中有一个 JAVA 项目 有多个包 但我的包中的某些文件有自己的main 方法并且可以自己运行 但是 如果我右键单击给定文件并选择 调试 运行 File main IntelliJ 将尝试构建包中的所有文件
  • ASP.NET MVC 3 中是否可以有多个依赖解析器?

    ASP NET MVC 3 中是否可以有多个依赖解析器 类似于 ModelBinder 和 Provider 的情况 我可以想到一种场景 拥有多个 容器 或 解析器 是有用的 那就是多租户 通过多租户 您可以在同一个 Web 应用程序中运行
  • 禁用 g++ 的返回值优化

    我需要在命令行上使用什么标志来禁用 g 编译器自动启用的返回值优化 fno elide constructors C 标准允许实现省略创建临时对象 该临时对象仅用于初始化相同类型的另一个对象 指定此选项会禁用该优化 并强制 G 在所有情况下
  • Android:调整位图大小而不损失质量

    在发布之前我确实搜索了整个网络 我的问题是 我无法在不损失图像质量的情况下调整位图大小 质量非常差并且像素化 我从相机获取位图 然后必须缩小它的尺寸 这样我就可以更快地将其上传到服务器 这是进行采样的函数 public Bitmap res
  • 继承自 HtmlHelper 而不是扩展它

    我正在创建一组用于渲染兼容的助手推特引导程序 http twitter github com bootstraphtml 在我看来 当谈到如何将这些方法组合在一起时 我有两种选择 扩展 HtmlHelper 在方法中添加 TB 前缀 创建一
  • Python正则表达式匹配<之前的单词

    所以我想匹配这样的东西 foo
  • 当前日期与日期字段之间的天数

    我有这个问题如果有人可以帮忙的话 有一个字段 date 在我的桌子上 table1 这是格式为的日期3 31 1988 M D y 我需要定义自该日期以来已经过去了多少天 我试图给出这个指示 SELECT DATEDIFF CURDATE
  • Angularjs,对表中选定的复选框应用操作

    我正在尝试学习 AngularJS 并实现此复选框 当我从网格中选择一些复选框并单击 删除 按钮时 应从选定的复选框中删除表中的数据 我尝试过但不知道如何实现它 请参阅我在 Plunker 上的这段代码 http plnkr co edit
  • 为什么 SELECT FOR UPDATE 只能在事务中起作用?

    我想我很困惑选择更新 https dev mysql com doc refman 5 0 en innodb locking reads html构造 例子 mysql gt select from employees2 EmpId Em
  • msm 包中出现错误:*** 捕获段错误 *** “内存未映射”

    我正在尝试使用 msm 包运行多状态模型 但遇到以下错误 caught segfault address 0x607c00032c60 cause memory not mapped The data dat long lt structu
  • 如何使用 JavaScript 来限制最小值/最大值之间的数字?

    我想限制两个值之间的数字 我知道在 PHP 中你可以这样做 number min max intval number 1 20 this will make number 1 if it s lower than 1 and 20 if i
  • 即使所选选项没有更改,是否有任何方法可以在 Chrome 中的 SELECT 元素上触发单击事件?

    我有一个 SELECT 元素 其内容 选项元素 通过 AJAX 加载 并在准备就绪时以及更改不同的 SELECT 时插入 两个 SELECT 都有两个 OPTION 元素附加到通过 AJAX 加载的元素列表中
  • PHP Pthreads 最新版本 3.1.6(64 位)未安装在 Apache 上

    我正在尝试为 PHP 安装最新的 pthreads 扩展 3 1 6 64 位 根据 pthreads 的作者建议 http github com krakjoe pthreads http github com krakjoe pthre
  • 何时支持 ng-if 与 ng-show/ng-hide?

    我明白那个ng show and ng hide影响元素上设置的类ng if控制元素是否呈现为 DOM 的一部分 有没有选择指南ng if over ng show ng hide或相反亦然 取决于您的用例 但总结一下差异 ng if将从
  • 在字头表中添加页码 C#

    我在word中创建了一个1x3表格作为我的标题 这就是我想要的样子 左侧文本 中间文本 页码 我希望 PageNumber 单元格看起来像这样 页码 X Y 我已经成功地完成了单元格 1 1 和 1 2 我发现这可以帮助我处理单元格 1 3
  • 如何从 getc 读取过去的 EOF?

    我正在编写一个 XOR 加密程序 该程序在加密期间工作正常 但在解密期间工作正常 这 char ca2 fgetc f 被卡在某一点并且之后不会发生解密 我对问题的最好猜测是 加密文件包含各种字符 一旦 fgetc 到达 EOF 标记 该标
  • spring-data-mongo - 可选查询参数?

    我正在使用 spring data mongo 和基于 JSON 的查询方法 并且不确定如何在搜索查询中允许可选参数 例如 假设我有以下功能 Query name regex 0 options i createdDate gte 1 lt
  • Swift 4 - 在 mac os 上使用 AVAssetWriter 进行 avfoundation 屏幕和音频录制 - 视频冻结

    我正在使用 Aperture 从屏幕录制音频和视频 我们需要降低视频的比特率 所以我尝试重写它并使用 AVAssetWriter 录制视频 我的实现基于 CustomCamera 项目 并且几乎可以工作 问题出在视频中 几秒钟后它就冻结了