How to get a avfoundation uiview to save a video on a imagevewivew

My swift code below uses a avfoudnation uiview to take a photo and save it on the imageview. All I want to do is be able to take a video and save in then have be displayed on the imageview if possible. I am not concern with anything else like playing the video. I added 2 funds startRecord and Save. Which are to be used to start record and save the video to the imageview.

    import UIKit;import AVFoundation



  class ViewController: UIViewController, AVCapturePhotoCaptureDelegate {



@IBOutlet var previewView : UIView!

@IBOutlet var captureImageView : UIImageView!

var captureSession: AVCaptureSession!
var stillImageOutput: AVCapturePhotoOutput!
var videoPreviewLayer: AVCaptureVideoPreviewLayer!

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // Setup your camera here...
    captureSession = AVCaptureSession()
    captureSession.sessionPreset = .medium


    guard let backCamera = AVCaptureDevice.default(for: AVMediaType.video)
        else {
            print("Unable to access back camera!")
            return
    }

    do {
        let input = try AVCaptureDeviceInput(device: backCamera)
        //Step 9
        stillImageOutput = AVCapturePhotoOutput()
        stillImageOutput = AVCapturePhotoOutput()

        if captureSession.canAddInput(input) && captureSession.canAddOutput(stillImageOutput) {
            captureSession.addInput(input)
            captureSession.addOutput(stillImageOutput)
            setupLivePreview()
        }
    }
    catch let error  {
        print("Error Unable to initialize back camera:  \(error.localizedDescription)")
    }
}

func setupLivePreview() {

    videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

    videoPreviewLayer.videoGravity = .resizeAspect
    videoPreviewLayer.connection?.videoOrientation = .portrait
    previewView.layer.addSublayer(videoPreviewLayer)

    //Step12
    DispatchQueue.global(qos: .userInitiated).async { //[weak self] in
        self.captureSession.startRunning()
        //Step 13
        DispatchQueue.main.async {
            self.videoPreviewLayer.frame = self.previewView.bounds
        }
    }


      }
        @IBAction func startRecord(_ sender: Any) {

            }
 @IBAction func Save(_ sender: Any) {

          }
@IBAction func didTakePhoto(_ sender: Any) {

    let settings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
    stillImageOutput.capturePhoto(with: settings, delegate: self)
}

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

    guard let imageData = photo.fileDataRepresentation()
        else { return }

    let image = UIImage(data: imageData)
    captureImageView.image = image
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.captureSession.stopRunning()
}

     }

Hi @timswift, are you essentially wanting to create a thumbnail of your video? If so, you can try creating a function to create a thumbnail image with the video URL then use that method to display the thumbnail in an imageView.

import AVKit

@IBOutlet weak var videoThumbnail: UIImageView!

func getThumbnailFromUrl(_ url: String?, _ completion: @escaping ((_ image: UIImage?)->Void)) {

    guard let url = URL(string: url ?? "") else { return }
    DispatchQueue.main.async {
        let asset = AVAsset(url: url)
        let assetImgGenerate = AVAssetImageGenerator(asset: asset)
        assetImgGenerate.appliesPreferredTrackTransform = true

        let time = CMTimeMake(value: 2, timescale: 1)
        do {
            let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
            let thumbnail = UIImage(cgImage: img)
            completion(thumbnail)
        } catch {
            print("Error :: ", error.localizedDescription)
            completion(nil)
        }
    }
}

self.getThumbnailFromUrl(videoURL) { [weak self] (img) in
        guard let _ = self else { return }
        if let img = img {
            self?.videoThumbnail.image = img
        }
    }

I will take at look at this thanks!

@gdelarosa in what func do I put self.getThumbnailFromUrl(videoURL) { [weak self] (img) in
guard let _ = self else { return }
if let img = img {
self?.imgThumbnail.image = img
}
} ?

You can place that method in the function that you will be retrieving the video URL from. The parameter is expecting a string and in the example “videoURL” would be where you’d place the url of your video.

So this would be like the fetch func?

I’d think so. If you’re fetching the url and other stuff then I’d probably put it there.

Best,
Gina

@gdelarosa A button is going to call the func but I don’t know what to put in the two highlighted blocks.

               @IBAction func Save(_ sender: Any) {
  //what do I put in the 2 highlighted blocks
getThumbnailFromUrl(<#T##url: String?##String?#>, <#T##completion: ((UIImage?) -> Void)##((UIImage?) -> Void)##(UIImage?) -> Void#>)}

Try creating a constant called videoURL then adding it into the getThumnailFromUrl method. Example below

  @IBAction func buttonAction(_ sender: Any) {
        let videoURL = "YourVideoURL"
    
    self.getThumbnailFromUrl(videoURL) { [weak self] (img) in
        guard let _ = self else { return }
        if let img = img {
            self?.videoThumnail.image = img
        }
    }
}

I have not personally tested this out myself, so it may not work and or have a runtime error. If you are unable to achieve your goal with this solution you can also try finding other examples online by searching video thumbnail to imageView in swift.

@gdelarosa how would I make previewView which is a uiview become the video URL?

Hi @timswift,
The videoURL is a fileURL that you would create from the video in your Resource directory of from an actual URL. If you are using a YoutTube Video then it offers Thumbnails in different sizes that you can get directly.

cheers,

@jayantvarma so If I wanted to take a snapshot from a video on a uiview that is already in the app. What would I do? I guess I would not use a video url because this has nothing to do with a online video.

hi @timswift,
I get that you already have a video in your view hierarchy. How are you playing that video? Is it from a local resource file in your app or is it captured from the camera and held in memory?

Eitherways, the Video URL that is important for AVAssetImageGenerator is not necessarily a remote video url, it can be a local file or by saving the in memory to a temp directory and passing the fileURL to that.

Even if you are getting the video from your Device (Photo Album) you would get a fileURL that you can use.

The other way you can capture and get a screenshot from a UIView irrespective of a video or not is to render the UIView as

  func snapshot(_ view: UIView) -> UIImage {
    let imageRenderer = UIGraphicsImageRenderer(bounds: view.bounds)
    return imageRenderer.image { context in
        layer.render(in: context)
    }
  }

Hope this resolves your issue

cheers,

This is what I got to compile func snapshot(_ view: UIView) → UIImage {
let imageRenderer = UIGraphicsImageRenderer(bounds: view.bounds)
return imageRenderer.image { context in
videoPreviewLayer.render(in: context as! CGContext)
}
}. Hope it works I am trying to import a video from photo gallery.

Hi @timswift

Did it work for you?

cheers,

This topic was automatically closed after 166 days. New replies are no longer allowed.