如何同时录制视频和播放音频(Swift教程)

5

所以你想要同时从用户的库中录制视频播放音乐?不用再找了,下面就是答案。

2个回答

10

对于音频播放,您将使用AVAudioPlayer。您所要做的就是将AVAudioPlayer声明为全局变量(我将其命名为audioPlayer)并实现以下代码。

在用户选择要播放的歌曲后,使用以下代码:

func mediaPicker(mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
    let pickerItem: MPMediaItem = mediaItemCollection.items[0]
    let songURL = pickerItem.valueForProperty(MPMediaItemPropertyAssetURL)
    if let sURL = songURL as? NSURL
    {
        songTitle = pickerItem.title!
        do
        {
            audioPlayer = try AVAudioPlayer(contentsOfURL: sURL)
        }
        catch
        {
            print("Can't Create Audio Player: \(error)")
        }
    }
    dismissViewControllerAnimated(true, completion: { () -> Void in
        audioPlayer.play()
    })
}

您还需要在viewDidLoad设置音频会话。如果您希望录制时播放音频,这非常重要:

 // Audio Session Setup
    do
    {
        try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
    }
    catch
    {
        print("Can't Set Audio Session Category: \(error)")
    }
    AVAudioSessionCategoryOptions.MixWithOthers
    do
    {
        try audioSession.setMode(AVAudioSessionModeVideoRecording)
    }
    catch
    {
        print("Can't Set Audio Session Mode: \(error)")
    }
    // Start Session
    do
    {
        try audioSession.setActive(true)
    }
    catch
    {
        print("Can't Start Audio Session: \(error)")
    }

现在我们来谈一下视频录制。您将使用AVCaptureSession。请将以下内容声明为全局变量:
let captureSession = AVCaptureSession()
var currentDevice: AVCaptureDevice?
var videoFileOutput: AVCaptureMovieFileOutput?
var cameraPreviewLayer: AVCaptureVideoPreviewLayer?

然后在viewDidLoad中配置会话。注意:视频预览在容器中,整个视频相关的代码在另一个视图控制器中,但只使用视图而不是容器也可以正常工作:

// Preset For 720p
captureSession.sessionPreset = AVCaptureSessionPreset1280x720

// Get Available Devices Capable Of Recording Video
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) as! [AVCaptureDevice]

// Get Back Camera
for device in devices
{
    if device.position == AVCaptureDevicePosition.Back
    {
        currentDevice = device
    }
}
let camera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

// Audio Input
let audioInputDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeAudio)

do
{
    let audioInput = try AVCaptureDeviceInput(device: audioInputDevice)

    // Add Audio Input
    if captureSession.canAddInput(audioInput)
    {
        captureSession.addInput(audioInput)
    }
    else
    {
        NSLog("Can't Add Audio Input")
    }
}
catch let error
{
    NSLog("Error Getting Input Device: \(error)")
}

// Video Input
let videoInput: AVCaptureDeviceInput
do
{
    videoInput = try AVCaptureDeviceInput(device: camera)

    // Add Video Input
    if captureSession.canAddInput(videoInput)
    {
        captureSession.addInput(videoInput)
    }
    else
    {
        NSLog("ERROR: Can't add video input")
    }
}
catch let error
{
    NSLog("ERROR: Getting input device: \(error)")
}

// Video Output
videoFileOutput = AVCaptureMovieFileOutput()
captureSession.addOutput(videoFileOutput)

// Show Camera Preview
cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
view.layer.addSublayer(cameraPreviewLayer!)
cameraPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
let width = view.bounds.width
cameraPreviewLayer?.frame = CGRectMake(0, 0, width, width)

// Bring Record Button To Front & Start Session
view.bringSubviewToFront(recordButton)
captureSession.startRunning()
print(captureSession.inputs)

然后您创建一个@IBAction,用于处理用户按下记录按钮时的操作(我只是使用了一个简单的按钮,将其制成了红色和圆形):

@IBAction func capture(sender: AnyObject) {
    do
    {
        initialOutputURL = try NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true).URLByAppendingPathComponent("output").URLByAppendingPathExtension("mov")
    }
    catch
    {
        print(error)
    }
    if !isRecording
    {
        isRecording = true

        UIView.animateWithDuration(0.5, delay: 0.0, options: [.Repeat, .Autoreverse, .AllowUserInteraction], animations: { () -> Void in
            self.recordButton.transform = CGAffineTransformMakeScale(0.75, 0.75)
            }, completion: nil)

        videoFileOutput?.startRecordingToOutputFileURL(initialOutputURL, recordingDelegate: self)
    }
    else
    {
        isRecording = false

        UIView.animateWithDuration(0.5, delay: 0, options: [], animations: { () -> Void in
            self.recordButton.transform = CGAffineTransformMakeScale(1.0, 1.0)
            }, completion: nil)
        recordButton.layer.removeAllAnimations()
        videoFileOutput?.stopRecording()
    }
}

接着,你只需要将视频保存到(很可能是)相机胶卷中即可。但我不会包含此部分内容。您必须自己付出一些努力。(提示:UISaveVideoAtPathToSavedPhotosAlbum

这就是使用AVFoundation同时录制视频和从库中播放音乐的方法。


Lawrence413,非常感谢您,这非常有帮助!!我有一个问题...是否有可能停止麦克风录制。我只想要视频和来自文件的音频。这可以在各种应用程序中完成,包括TikTok,Instagram和其他应用程序。我尝试了很多方法,但无法解决。任何帮助都将不胜感激! - LilMoke
我不确定,但我认为你不能这样做。这可能是系统音频,我不认为开发人员可以访问它。我相信Instagram的工作方式是将视频与歌曲合并,但你不能录制。我不知道TikTok。即使是苹果的屏幕录制应用程序也无法记录系统音频,因此这应该是一个明确的指示,表明你不能这样做。 - Lawrence413
实际上它确实记录系统音频!而且这是可能的! - Kev Wats
@LilMoke 你好,你能找到任何说明如何关闭麦克风但同时获取音频和视频的链接吗?或者你已经弄清楚了吗? - Lance Samaria
@KevWats 我正在尝试像Instagram一样访问系统音频输出。我该如何实现? - Quentin Hayot

0

一旦您像下面这样设置了AVAudioSession,它就会正常工作。

try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord, mode: AVAudioSession.Mode.videoRecording, options: AVAudioSession.CategoryOptions.mixWithOthers)


有什么其他的提示吗?如果我依次播放两个正在录制的文件,其中一个文件只有几秒钟的音频,那么录制文件最终将没有音频。请帮帮我。 - Paresh. P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接