iOS視頻添加水印兩種方式(不用到第三方框架)

1箩张、視頻加水印,并保存到沙盒當(dāng)中

//原視頻sureasset较锡,有外界傳進來

AVURLAsset *asset = (AVURLAsset *)[self addPhotoTitleWithAsset:sureasset][0];

? ? AVMutableVideoComposition *mainCompositionInst = [self addPhotoTitleWithAsset:sureasset][1];

? ? sureasset = asset;


? ? AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset: sureasset presetName:AVAssetExportPresetMediumQuality];

? ? NSString *failPath = [self getVideosPath:@"localVideo"];//獲取路徑

? ? NSURL *filUrl = [NSURL fileURLWithPath:failPath];

? ? session.outputURL = filUrl;//視頻輸出地址

? ? session.outputFileType = AVFileTypeMPEG4;//AVFileTypeQuickTimeMovie;//AVFileTypeMPEG4;


? ? // 這個一般設(shè)置為yes(指示輸出文件應(yīng)針對網(wǎng)絡(luò)使用進行優(yōu)化业稼,例如QuickTime電影文件應(yīng)支持“快速啟動”)

? ? session.shouldOptimizeForNetworkUse = YES;

? ? // 文件的最大多大的設(shè)置

? ? session.fileLengthLimit = 30 * 1024 * 1024;


? ? session.shouldOptimizeForNetworkUse = YES;

? ? session.videoComposition = mainCompositionInst;


? ? [session exportAsynchronouslyWithCompletionHandler:^(void){

? ? ? ? dispatch_async(dispatch_get_main_queue(), ^{

? ? ? ? ? ? //視頻導(dǎo)入成功

? ? ? ? ? ? //failPath為本地視頻地址

? ? ? ? ? ? completeBlock(failPath,YES);

? ? ? ? });

? ? }];


//獲取路徑

- (NSString *)getVideosPath:(NSString *)videoName{

? ? NSString *documents = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];

? ? documents = [documents stringByAppendingPathComponent:@"CCTV5"];

? ? documents = [self action_addFiles:documents];//判斷文件是否存在

? ? NSString *failPath = [documents stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4",videoName]];

? ? return failPath;

}


#pragma mark- 視頻加水印

//添加水印

-(NSArray *)addPhotoTitleWithAsset:(AVAsset *)videoAsset

{

? ? //1 創(chuàng)建AVAsset實例

? ? //AVURLAsset*videoAsset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:path]];


? ? AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];



? ? //3 視頻通道

? ? AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? preferredTrackID:kCMPersistentTrackID_Invalid];

? ? [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)

? ? ? ? ? ? ? ? ? ? ? ? ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject]

? ? ? ? ? ? ? ? ? ? ? ? atTime:kCMTimeZero error:nil];



? ? //2 音頻通道

? ? AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? preferredTrackID:kCMPersistentTrackID_Invalid];

? ? [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)

? ? ? ? ? ? ? ? ? ? ? ? ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] firstObject]

? ? ? ? ? ? ? ? ? ? ? ? atTime:kCMTimeZero error:nil];


? ? //3.1 AVMutableVideoCompositionInstruction 視頻軌道中的一個視頻,可以縮放蚂蕴、旋轉(zhuǎn)等

? ? AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];

? ? mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration);


? ? // 3.2 AVMutableVideoCompositionLayerInstruction 一個視頻軌道低散,包含了這個軌道上的所有視頻素材

? ? AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];


? ? [videolayerInstruction setOpacity:0.0 atTime:videoAsset.duration];


? ? // 3.3 - Add instructions

? ? mainInstruction.layerInstructions = [NSArray arrayWithObjects:videolayerInstruction,nil];


? ? //AVMutableVideoComposition:管理所有視頻軌道,水印添加就在這上面

? ? AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];


? ? AVAssetTrack *videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject];

? ? CGSize naturalSize = videoAssetTrack.naturalSize;

? ? //防崩潰處理骡楼,這個width可能為空熔号,按比例給他值

? ? if (naturalSize.width == 0) {

? ? ? ? CGFloat a = (1280.f / 720);

? ? ? ? naturalSize.width =? a * naturalSize.height;

? ? }


? ? float renderWidth, renderHeight;

? ? renderWidth = naturalSize.width;

? ? renderHeight = naturalSize.height;

? ? mainCompositionInst.renderSize = CGSizeMake(renderWidth, renderHeight);

? ? mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];

? ? mainCompositionInst.frameDuration = CMTimeMake(1, 30);



? ? [self applyVideoEffectsToComposition:mainCompositionInst size:naturalSize];

? ? NSArray *arrar = [NSArray arrayWithObjects:mixComposition,mainCompositionInst, nil];

? ? return arrar;;

}

/**

設(shè)置水印及其對應(yīng)視頻的位置

@param composition 視頻的結(jié)構(gòu)

@param size 視頻的尺寸

*/

- (void)applyVideoEffectsToComposition:(AVMutableVideoComposition *)composition size:(CGSize)size

{

? ? // 文字

? ? CATextLayer *subtitle1Text = [[CATextLayer alloc] init];

? ? //? ? [subtitle1Text setFont:@"Helvetica-Bold"];

? ? [subtitle1Text setFontSize:36];

? ? [subtitle1Text setFrame:CGRectMake(10, size.height-10-230, size.width, 100)];

? ? [subtitle1Text setString:@"央視體育5 水印"];

? ? //? ? [subtitle1Text setAlignmentMode:kCAAlignmentCenter];

? ? [subtitle1Text setForegroundColor:[[UIColor whiteColor] CGColor]];


? ? //圖片

? ? CALayer*picLayer = [CALayer layer];


? ? //picLayer.contents = (id)[UIImage imageNamed:@"CTVITTRIMSource.bundle/QQ"].CGImage; //本地圖片

? ? picLayer.contents = (id)self.videoWaterMarkImage.CGImage; //本地圖片2

? ? //NSString *imageUrl = @"http://p1.img.cctvpic.com/photoAlbum/templet/special/PAGEQ1KSin2j2U5FERGWHp1h160415/ELMTnGlKHUJZi7lz19PEnqhM160415_1460715755.png";

? ? //picLayer.contents = (id)[self getImageFromURL:imageUrl].CGImage; //遠程圖片

? ? CGFloat width = 63;

? ? CGFloat leftMargin = 16 * [self scaleSizeWithHeight:size.height];

? ? CGFloat topMargin = 20 * [self scaleSizeWithHeight:size.height];

? ? if (self.videoWaterMarkPlace == WaterMarkTopLeft) {

? ? ? ? picLayer.frame = CGRectMake(leftMargin, size.height-topMargin-[self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*width, [self scaleSizeWithHeight:size.height]*width);

? ? }

? ? if (self.videoWaterMarkPlace == WaterMarkBottomLeft) {

? ? ? ? picLayer.frame = CGRectMake(leftMargin, 20, [self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*50);

? ? }

? ? if (self.videoWaterMarkPlace == WaterMarkTopRight) {

? ? ? ? picLayer.frame = CGRectMake(size.width - 20 - [self scaleSizeWithHeight:size.height]*50, size.height-20-[self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*50);

? ? }

? ? if (self.videoWaterMarkPlace == WaterMarkBottomRight) {

? ? ? ? picLayer.frame = CGRectMake(size.width - 20 - [self scaleSizeWithHeight:size.height]*50, 20, [self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*50);


? ? }


? ? // 2 - The usual overlay

? ? CALayer *overlayLayer = [CALayer layer];

? ? [overlayLayer addSublayer:picLayer];

? ? //? ? [overlayLayer addSublayer:subtitle1Text];

? ? overlayLayer.frame = CGRectMake(0, 0, size.width, size.height);

? ? [overlayLayer setMasksToBounds:YES];


? ? CALayer *parentLayer = [CALayer layer];

? ? CALayer *videoLayer = [CALayer layer];

? ? parentLayer.frame = CGRectMake(0, 0, size.width, size.height);

? ? videoLayer.frame = CGRectMake(0, 0, size.width, size.height);

? ? [parentLayer addSublayer:videoLayer];

? ? [parentLayer addSublayer:overlayLayer];


? ? composition.animationTool = [AVVideoCompositionCoreAnimationTool

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];


}

//ios 從網(wǎng)絡(luò)上獲取圖片

-(UIImage *) getImageFromURL:(NSString *)fileURL {

? ? //https://vod.cctv.cn/cctvsports/cctv5/img/advertisingImage.jpg

? ? NSLog(@"執(zhí)行圖片下載函數(shù)");


? ? UIImage * result;


? ? NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];


? ? result = [UIImage imageWithData:data];


? ? return result;


}



2、另一種實現(xiàn)方式

? ? //? ? [self applyVideoEffectsToComposition:mainCompositionInst size:naturalSize];


? ? CIFilter *watermarkFilter = [CIFilter filterWithName:@"CISourceOverCompositing"];


? ? mainCompositionInst = [AVMutableVideoComposition videoCompositionWithAsset:videoAsset applyingCIFiltersWithHandler:^(AVAsynchronousCIImageFilteringRequest * _Nonnull request) {


? ? ? ? CIImage *watermarkImage? =? [[CIImage alloc] initWithCGImage:self.videoWaterMarkImage.CGImage];


? ? ? ? CIImage *source = request.sourceImage;


? ? ? ? [watermarkFilter setValue:source forKey:kCIInputBackgroundImageKey];


? ? ? ? [watermarkFilter setValue:[watermarkImage imageByApplyingTransform:CGAffineTransformMakeScale(0.5, 0.5)] forKey:kCIInputImageKey];




? ? ? ? [watermarkFilter setValue:[watermarkImage imageByApplyingTransform:CGAffineTransformMakeTranslation(14, source.extent.size.height - 14 - watermarkImage.extent.size.height)] forKey:kCIInputImageKey];

? ? ? ? [request finishWithImage:watermarkFilter.outputImage context:nil];


? ? }];



? ? //? ? ? //? ? // 4 - 輸出路徑

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸟整,一起剝皮案震驚了整個濱河市引镊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌篮条,老刑警劉巖弟头,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涉茧,居然都是意外死亡赴恨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門伴栓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伦连,“玉大人雨饺,你說我怎么就攤上這事』蟠荆” “怎么了额港?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長歧焦。 經(jīng)常有香客問我移斩,道長,這世上最難降的妖魔是什么绢馍? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任叹哭,我火速辦了婚禮,結(jié)果婚禮上痕貌,老公的妹妹穿的比我還像新娘。我一直安慰自己糠排,他們只是感情好舵稠,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著入宦,像睡著了一般哺徊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乾闰,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天落追,我揣著相機與錄音,去河邊找鬼涯肩。 笑死轿钠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的病苗。 我是一名探鬼主播疗垛,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼硫朦!你這毒婦竟也來了贷腕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤咬展,失蹤者是張志新(化名)和其女友劉穎泽裳,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體破婆,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡涮总,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了荠割。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妹卿。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡旺矾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出夺克,到底是詐尸還是另有隱情箕宙,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布铺纽,位于F島的核電站柬帕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏狡门。R本人自食惡果不足惜陷寝,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望其馏。 院中可真熱鬧凤跑,春花似錦、人聲如沸叛复。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽褐奥。三九已至咖耘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撬码,已是汗流浹背儿倒。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呜笑,地道東北人夫否。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像蹈垢,于是被迫代替她去往敵國和親慷吊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容