iOS 应用 Display Recorder 如何在不使用私有 API 的情况下录制屏幕

ios屏幕

1个回答

写回答

王良杰

2025-06-16 17:15

+ 关注

IOS
IOS

IOS 应用 Display Recorder 是一款功能强大的屏幕录制应用程序,它可以在不使用私有 API 的情况下录制屏幕。接下来,我们将介绍如何实现屏幕录制的功能,并提供案例代码供参考。

屏幕录制的原理

IOS 平台上,要实现屏幕录制的功能,需要使用到 Core Media 和 AV Foundation 框架。Core Media 提供了底层的媒体处理功能,而 AV Foundation 则提供了高级的媒体操作接口。

录制屏幕的步骤

1. 创建一个 AVAssetWriter 对象,用于将屏幕录制的内容写入到文件中。

2. 创建一个 AVAssetWriterInput 对象,并将其添加到 AVAssetWriter 对象中。AVAssetWriterInput 对象用于接收屏幕录制的内容。

3. 获取屏幕的分辨率和刷新率,并根据这些参数创建一个 AVAssetWriterInputPixelBufferAdaptor 对象。AVAssetWriterInputPixelBufferAdaptor 对象用于将屏幕录制的内容转换成像素数据。

4. 创建一个 CADisplayLink 对象,并将其添加到主运行循环中。CADisplayLink 对象用于定时获取屏幕的内容。

5. 在 CADisplayLink 的回调方法中,获取屏幕的内容,并将其写入到 AVAssetWriterInputPixelBufferAdaptor 对象中。

示例代码

下面是一个简单的示例代码,演示如何在 IOS 应用中录制屏幕

Swift

import UIKit

import AVFoundation

class ScreenRecorder {

private var assetWriter: AVAssetWriter?

private var assetWriterInput: AVAssetWriterInput?

private var pixelBufferAdaptor: AVAssetWriterInputPixelBufferAdaptor?

private var displayLink: CADisplayLink?

func startRecording() {

let screenSize = UIScreen.mAIn.bounds.size

let outputFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("screenRecording.mp4")

do {

assetWriter = try AVAssetWriter(url: outputFileURL, fileType: .mp4)

let outputSettings = [

AVVIDEOCodecKey: AVVIDEOCodecType.h264,

AVVIDEOWidthKey: screenSize.width,

AVVIDEOHeightKey: screenSize.height

] as [String : Any]

assetWriterInput = AVAssetWriterInput(mediaType: .vIDEO, outputSettings: outputSettings)

assetWriterInput?.expectsMediaDatAInRealTime = true

let pixelBufferAttributes = [

kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32ARGB,

kCVPixelBufferWidthKey as String: screenSize.width,

kCVPixelBufferHeightKey as String: screenSize.height

] as [String : Any]

pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: assetWriterInput!, sourcePixelBufferAttributes: pixelBufferAttributes)

assetWriter?.add(assetWriterInput!)

displayLink = CADisplayLink(target: self, selector: #selector(captureScreen))

displayLink?.add(to: .mAIn, forMode: .default)

assetWriter?.startWriting()

assetWriter?.startSession(atSourceTime: .zero)

} catch {

print("FAIled to start screen recording: \(error)")

}

}

@objc private func captureScreen() {

guard let assetWriterInput = assetWriterInput, assetWriterInput.isReadyForMoreMediaData else {

return

}

guard let pixelBufferPool = pixelBufferAdaptor?.pixelBufferPool else {

return

}

let pixelBuffer = createPixelBuffer(from: UIScreen.mAIn)

pixelBufferAdaptor?.append(pixelBuffer, withPresentationTime: .zero)

}

private func createPixelBuffer(from view: UIView) -> CVPixelBuffer? {

let screenSize = UIScreen.mAIn.bounds.size

let scale = UIScreen.mAIn.scale

UIGraphicsBeginImageContextWithOptions(screenSize, false, scale)

guard let context = UIGraphicsGetcurrentContext() else {

return nil

}

view.layer.render(in: context)

guard let image = UIGraphicsGetImageFromCurrentImageContext()?.cgImage else {

return nil

}

UIGraphicsEndImageContext()

var pixelBuffer: CVPixelBuffer?

let status = CVPixelBufferPoolCreatePixelBuffer(nil, pixelBufferPool, &pixelBuffer)

if status != kCVReturnSuccess {

return nil

}

CVPixelBufferLockBaseAddress(pixelBuffer!, .readOnly)

let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)

let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer!)

let bytesPerPixel = 4

let context = CGContext(

data: pixelData,

width: Int(screenSize.width),

height: Int(screenSize.height),

bitsPerComponent: 8,

bytesPerRow: bytesPerRow,

space: CGColorSpaceCreateDeviceRGB(),

bitmapInfo: CGImageAlphAInfo.noneSkipFirst.rawValue

)

context?.draw(image, in: CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height))

CVPixelBufferUnlockBaseAddress(pixelBuffer!, .readOnly)

return pixelBuffer

}

func stopRecording() {

displayLink?.invalidate()

displayLink = nil

assetWriterInput?.markAsFinished()

assetWriter?.finishWriting {

if self.assetWriter?.status == .completed {

// 屏幕录制完成

} else {

// 屏幕录制失败

}

}

}

}

参考文章

- [AVFoundation Programming Guide](Apple.com/library/archive/documentation/AudioVIDEO/Conceptual/AVFoundationPG/Articles/00_Introduction.html">https://developer.Apple.com/library/archive/documentation/AudioVIDEO/Conceptual/AVFoundationPG/Articles/00_Introduction.html)

- [AVAssetWriter](https://developer.Apple.com/documentation/avfoundation/avassetwriter)

- [CADisplayLink](https://developer.Apple.com/documentation/quartzcore/CADisplaylink)

举报有用(4分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号