3

iPhoneの既存のビデオにテキスト(クローズドキャプションスタイル)を追加することに興味があります。stackoverflowでのこれに対するいくつかの解決策は、ビデオをオーバーレイするために透明なUIViewを追加することを提案します。それはすべて良いことですが、それを「新しく変更されたビデオ」として保存することはできません。

私が見る唯一の解決策は、テキストを取得し、ビデオから1つのフレームを取得し、そのフレームにテキストを追加し、変更されたフレームとテキストをビデオにプッシュして、ビデオの元のフレームを置き換えることです。

ビデオからフレームを取り出す方法(テキストの追加を理解できると思います)、そしてフレームをビデオに戻す方法を知っている人はいますか?何かアイデアがある場合、またはチュートリアルを知っている場合は、それをいただければ幸いです。

4

4 に答える 4

5

フレームごとにこれを行う必要はありません。AVFoundationは、iOS4.0以降の字幕をサポートしています。

たとえば、 AVMutableCompositionを作成してから、ビデオの上に字幕トラックを追加することができます。AVMediaTypeSubtitleは、字幕のタイプ(またはクローズドキャプションの場合はAVMediaTypeClosedCaption)です。次に、コンポジションをプレーヤーまたはAVAssetWriterのいずれかにフィードできます。すべての手間を省きます。

于 2013-03-18T16:35:54.570 に答える
1

あなたが言ったことによると、ここにあなたが学ぶことができる例があります。

ここに画像の説明を入力してください

上の写真からわかるように、ビデオにボーダー、オーバーレイ、字幕など、好きなものを追加できます。

http://www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos

于 2014-12-19T09:50:59.063 に答える
1

AvFoundationフレームワークを介してビデオを編集できます...

これが例です。

var AssetTrack = AVAsset.assetWithURL(filePath1)as!AVURLAsset var mutableComposition = AVMutableComposition()

    // Step - 1  pass url to  avasset

    // video

    var compositionVideoTrack = AVMutableCompositionTrack()
    compositionVideoTrack = mutableComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())


    var assetVideoTrack = assetTrack.tracksWithMediaType(AVMediaTypeVideo)[0] as! AVAssetTrack
    compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero , assetTrack.duration), ofTrack: assetVideoTrack, atTime: kCMTimeZero, error: nil)

    // audio

    var compositionAudioTrack = AVMutableCompositionTrack()
    compositionAudioTrack = mutableComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())

    var assetAudioTrack = assetTrack.tracksWithMediaType(AVMediaTypeAudio)[0] as! AVAssetTrack
    compositionAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero , assetTrack.duration), ofTrack: assetAudioTrack, atTime: kCMTimeZero, error: nil)

    var videoAssetOrientation_: UIImageOrientation = .Up
    var isVideoAssetPortrait_: Bool = false

    var videoTransform: CGAffineTransform = assetTrack.preferredTransform



    var videosize = CGSize()
    videosize = assetVideoTrack.naturalSize

    var parentLayer = CALayer()
    var videoLayer = CALayer()
    var textLayer = CALayer()

    parentLayer.frame = CGRectMake(0, 0, videosize.width, videosize.height)
    videoLayer.frame = CGRectMake(0, 0, videosize.width, videosize.height)
    textLayer.frame = CGRectMake(0, 0, videosize.width, videosize.height)

    parentLayer.addSublayer(videoLayer)

    if drawingView.image != nil
    {
        var drawingLayer = CALayer()
        drawingLayer.frame = CGRectMake(0, 0, videosize.width, videosize.height)
        drawingLayer.contents = drawingView.image.CGImage

        var image = UIImage()
        parentLayer.addSublayer(drawingLayer)

    }


    var textV = UIView()
    textV.backgroundColor = UIColor.clearColor()
    textV.layer.backgroundColor = UIColor.clearColor().CGColor
    textV.frame = CGRectMake(self.captureView.frame.size.width, 0, self.captureView.frame.size.width, self.captureView.frame.size.height)

    var textL = UILabel()
    textL = textShowOnPreview
    textV.addSubview(textL)

    if textL != ""
    {
        UIGraphicsBeginImageContext(textV.bounds.size)
        textV.layer.renderInContext(UIGraphicsGetCurrentContext())
        var image1: UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        if ( TextAnimation == "")
        {
            textLayer.contents = image1.CGImage
            parentLayer.addSublayer(textLayer)
        }

        else if  ( TextAnimation == "flip")
        {

            var overlayer1 = CALayer()
            overlayer1.backgroundColor = UIColor.clearColor().CGColor
            let screenSize: CGRect = UIScreen.mainScreen().bounds
            overlayer1.contents = image1.CGImage
            overlayer1.masksToBounds = true
            overlayer1.frame = CGRectMake(videosize.width/2-300, videosize.height/2 - 400, videosize.width,videosize.width);
            var   animation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation")
            animation.duration=5.0;
            animation.repeatCount=5;
            animation.autoreverses = true;
            // rotate from 0 to 360
            animation.fromValue = 0
            animation.toValue = (2.0 * M_PI);
            animation.beginTime = AVCoreAnimationBeginTimeAtZero;
            overlayer1.addAnimation(animation, forKey:"rotation")
            [parentLayer .addSublayer(overlayer1)]

        }
        else if ( TextAnimation == "fade")
        {

                       //opacity
            var overlayer1 = CALayer()
            overlayer1.backgroundColor = UIColor.clearColor().CGColor
            overlayer1.contents = image1.CGImage
            overlayer1.masksToBounds = true

            overlayer1.frame = CGRectMake(videosize.width/2 - 300,  videosize.height/2 - 100 , videosize.width+20, videosize.width);
            var   animation : CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
            animation.duration = 2.0;
            animation.repeatCount = 3;
            animation.autoreverses = true;
            // rotate from 0 to 360

            animation.fromValue = 0.5;
            animation.toValue = 1.0;
            animation.beginTime = AVCoreAnimationBeginTimeAtZero;

            overlayer1.addAnimation(animation, forKey:"scale")
            [parentLayer .addSublayer(overlayer1)]

        }
        else if ( TextAnimation == "bounce")
        {
            var overlayer1 = CALayer()

            var bounce : CABasicAnimation = CABasicAnimation (keyPath:"position.y");
            overlayer1.backgroundColor = UIColor.clearColor().CGColor
            overlayer1.contents = image1.CGImage
            overlayer1.masksToBounds = true
            overlayer1.frame = CGRectMake(videosize.width/2 - 300,  videosize.height/2 - 100 , videosize.width, videosize.width);
            bounce.duration = 1.0;
            bounce.fromValue =  overlayer1.frame.origin.y

            bounce.toValue =  overlayer1.frame.origin.y - 100
            bounce.repeatCount = 10
            bounce.autoreverses = true;
            overlayer1.addAnimation(bounce, forKey: "y")

            var animation = CABasicAnimation(keyPath: "transform.scale")
            animation.toValue = NSNumber(float: 0.9)
            animation.duration = 1.0
            animation.repeatCount = 10;
            animation.autoreverses = true
            overlayer1.addAnimation(animation, forKey: nil)
             [parentLayer .addSublayer(overlayer1)]

        }

    }

    var mutableVideoComposition = AVMutableVideoComposition()
    mutableVideoComposition.frameDuration = CMTimeMake(1, 30)
    mutableVideoComposition.renderSize = videosize

    mutableVideoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer)


    var passThroughInstruction = AVMutableVideoCompositionInstruction()
    passThroughInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, mutableComposition.duration)


    var passThroughLayerInstruction = AVMutableVideoCompositionLayerInstruction()


    // video

    var assestVideoMutableCompositionVideo = mutableComposition.tracksWithMediaType(AVMediaTypeVideo)[0] as! AVAssetTrack
    passThroughLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: assestVideoMutableCompositionVideo)



    if isVideoAssetPortrait_ == false
    {

        var FirstAssetScaleFactor: CGAffineTransform = CGAffineTransformMakeScale(1, 1)

        passThroughLayerInstruction.setTransform(CGAffineTransformConcat(assetVideoTrack.preferredTransform, FirstAssetScaleFactor), atTime: kCMTimeZero)

    }


    passThroughInstruction.layerInstructions = [passThroughLayerInstruction]
    mutableVideoComposition.instructions = [passThroughInstruction]

    let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as! NSURL
    let filePath = documentsURL.URLByAppendingPathComponent("NewWatermarkedVideo.mov") as NSURL


    var fileManager:NSFileManager = NSFileManager.defaultManager()
    fileManager.removeItemAtURL(filePath, error: nil)

   var exporter: AVAssetExportSession = AVAssetExportSession(asset: mutableComposition, presetName: AVAssetExportPresetMediumQuality)
    exporter.videoComposition = mutableVideoComposition
    exporter.outputFileType = AVFileTypeQuickTimeMovie
    exporter.outputURL = filePath
    exporter.shouldOptimizeForNetworkUse = true
    self.captureView.addSubview(textShowOnPreview)

    exporter.exportAsynchronouslyWithCompletionHandler({() -> Void in

        println(exporter.status)

        if  exporter.status == AVAssetExportSessionStatus.Completed
        {


            dispatch_async(dispatch_get_main_queue(), { () -> Void in




                MBProgressHUD.hideAllHUDsForView(self.view, animated: true)

                self.topicSelectedImage.highlighted = false
                self.timelineSelectedImage.highlighted = false
                self.selectCat = ""
                self.postView.hidden = false

            })

            println("Completed")
            self.mediaData =  NSData(contentsOfURL:filePath, options: nil, error: nil)!


            var err: NSError? = nil
            var asset = AVURLAsset(URL: filePath, options: nil)
            var imgGenerator = AVAssetImageGenerator(asset: asset)
            var cgImage = imgGenerator.copyCGImageAtTime(CMTimeMake(0, 30), actualTime: nil, error: &err)
            var uiImage = UIImage(CGImage: cgImage)!
            self.videoThumbData = UIImageJPEGRepresentation(uiImage, 0.1)

            var assetTrack = AVAsset.assetWithURL(filePath) as! AVURLAsset
            self.videoTime = Int(CMTimeGetSeconds(assetTrack.duration)) + 3

            println(self.videoTime)


        }
        else if exporter.status == AVAssetExportSessionStatus.Cancelled
        {


        }
        else if exporter.status == AVAssetExportSessionStatus.Failed
        {


        }
    })
于 2016-04-21T06:14:54.110 に答える
0

フレームごとにムービーを編集したい場合は、AVReaderWriterを使用してください。OS X Appleのサンプルコードですが、AVFoundationはほとんど変更を加えずに両方のプラットフォームで利用できます。

于 2014-07-22T17:51:42.813 に答える