PKShortVideo README.md

PKShortVideo


CocoaPods
CocoaPods

CocoaPods
CocoaPods

Support
Support

A video library like WeChat short video for iOS.
Related Articles:iOS仿微信小視頻功能開發優化記錄

sc1
sc1

Features

  • Short video playback in chat interface, the use of GPUImage-based OpenGL ES hardware accelerated playback video
  • Short video can click to enlarge playback, using the AVPlayer
  • Provide a short video capture, to support custom resolution video capture, has a basic style, and provides the basis of switching cameras, recording, playback, re-recording function, the use of AVCaptureSession + AVCaptureVideoDataOutput and AVCaptureAudioDataOutput direct output video

Installation

Import <YYKit/YYKit.h>.

  1. Add pod 'PKShortVideo' to your Podfile.
  2. Run pod install or pod update.
  3. Import "PKShortVideo.h".

Usage

When Video recording, OutputFilePath parameters for the recording after the completion of the output video file path, OutputSize is the output video resolution.

Use default UI interface to record video (PKRecordShortVideoViewController)

Enter the recording interface

//跳轉默認錄制視頻ViewController
PKRecordShortVideoViewController *viewController = [[PKRecordShortVideoViewController alloc] initWithOutputFilePath:path outputSize:CGSizeMake(320, 240) themeColor:[UIColor colorWithRed:0/255.0 green:153/255.0 blue:255/255.0 alpha:1]];
//通過代理回調
viewController.delegate = self;
[self presentViewController:viewController animated:YES completion:nil];

Record complete callback

#pragma mark - PKRecordShortVideoDelegate
//視頻拍攝完成輸出圖片
- (void)didFinishRecordingToOutputFilePath:(NSString *)outputFilePath {
    //自定義的生成小視頻聊天對象方法
    [self.demoData addShortVideoMediaMessageWithVideoPath:outputFilePath];
    //JSQMessagesViewController的完成發送滾動到底端方法
    [self finishSendingMessageAnimated:YES];
}

When you use a custom UI to record video (PKShortVideoRecorder)

Creates a recording object

//創建視頻錄制對象
self.recorder = [[PKShortVideoRecorder alloc] initWithOutputFilePath:self.outputFilePath outputSize:self.outputSize];
//通過代理回調
self.recorder.delegate = self;
//錄制時需要獲取預覽顯示的layer,根據情況設置layer屬性,顯示在自定義的界面上
AVCaptureVideoPreviewLayer *previewLayer = [self.recorder previewLayer];
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.frame = CGRectMake(0, 44, kScreenWidth, PKPreviewLayerHeight);
[self.view.layer insertSublayer:previewLayer atIndex:0];

Start preview camera work

//開始預覽攝像頭工作
[self.recorder startRunning];

swap front and back camera

//切換前后攝像頭
[self.recorder swapFrontAndBackCameras];

startRecording

//開始錄制視頻
[self.recorder startRecording];

stopRecording

//停止錄制
[self.recorder stopRecording];

Video recorded successful callback

//視頻錄制結束回調
- (void)recorder:(PKShortVideoRecorder *)recorder didFinishRecordingToOutputFilePath:(NSString *)outputFilePath error:(NSError *)error {
//錄制成功返回路徑,錄制失敗返回錯誤對象
}

When Video playback, OutputFilePath parameters for the recording is completed after the output video file path, previewImage is a video preview.

Chat interface to play (due to different chat framework, here only JSQMessagesViewController to demonstrate)

Chat object creation

- (void)addShortVideoMediaMessageWithVideoPath:(NSString *)videoPath  playType:(PKPlayType)type {
    //PKShortVideoItem為遵循JSQMessagesViewController的規范創建的媒體(非文字)類型
    //previewImage參數為視頻的預覽圖片
    
    switch (type) {
        case PKPlayTypeOpenGL: {
            PKShortVideoItem *videoItem = [[PKShortVideoItem alloc] initWithVideoPath:videoPath previewImage:[UIImage pk_previewImageWithVideoURL:[NSURL fileURLWithPath:videoPath]]];
            //創建message對象
            JSQMessage *videoMessage = [JSQMessage messageWithSenderId:kJSQDemoAvatarIdSquires
                                                           displayName:kJSQDemoAvatarDisplayNameSquires
                                                                 media:videoItem];
            //把創建聊天對象加入聊天數組
            [self.messages addObject:videoMessage];
        }
            break;
            
        case PKPlayTypeAVPlayer: {
            PKShortVideoItem2 *videoItem = [[PKShortVideoItem2 alloc] initWithVideoPath:videoPath previewImage:[UIImage pk_previewImageWithVideoURL:[NSURL fileURLWithPath:videoPath]]];
            //創建message對象
            JSQMessage *videoMessage = [JSQMessage messageWithSenderId:kJSQDemoAvatarIdSquires
                                                           displayName:kJSQDemoAvatarDisplayNameSquires
                                                                 media:videoItem];
            //把創建聊天對象加入聊天數組
            [self.messages addObject:videoMessage];
        }
            break;
    }

}

The chat object is attached to the internal implementation of the media object

You can use the PKChatMessagePlayerView based on OpenGL and PKPlayerView based on AVPlayer, because PKChatMessagePlayerView to achieve the realization of OpenGL by reflecting the current is not stable, it is recommended to use PKPlayerView, using the interface exactly the same.

//當前尺寸
CGSize size = [self mediaViewDisplaySize];
//實例化播放view
self.playerView = [[PKPlayerView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height) videoPath:self.videoPath previewImage:self.image];

If the demand strategy is very complex, need to determine whether the group or friends, a variety of network conditions, whether to download or automatically play, still need to customize the chat object attached media objects, PKChatMessagePlayerView only in the presence of video playback.

//開始播放小視頻
- (void)play {
    [self.playerView play];
}
//結束播放視頻
- (void)pause {
    [self.playerView stop];
}

Chat interface control to achieve

For performance reasons, the best in the chat interface to do when the display is played, do not show the time to stop playing.

//將要結束顯示時停止播放
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    JSQMessage *message = self.demoData.messages[indexPath.item];
    if ([message.media isKindOfClass:[PKShortVideoItem class]]) {
        PKShortVideoItem *item = (PKShortVideoItem *)message.media;
        [item pause];
    }
}

//將要顯示時播放
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    JSQMessage *message = self.demoData.messages[indexPath.item];
    if ([message.media isKindOfClass:[PKShortVideoItem class]]) {
        PKShortVideoItem *item = (PKShortVideoItem *)message.media;
        [item play];
    }
}

Click to Full Screen play

//點擊消息是跳轉播放
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath {
    JSQMessage *message = self.demoData.messages[indexPath.item];
    //判斷媒體消息類型
    if ([message.media isKindOfClass:[PKShortVideoItem class]]) {
        PKShortVideoItem *item = (PKShortVideoItem *)message.media;
        //跳轉全屏播放小視頻界面
        PKFullScreenPlayerViewController *viewController = [[PKFullScreenPlayerViewController alloc] initWithVideoPath:item.videoPath previewImage:[UIImage pk_previewImageWithVideoURL:[NSURL fileURLWithPath:item.videoPath]]];
        [self presentViewController:viewController animated:NO completion:NULL];
    }
}

Requirements

This library requires iOS 7.0 and Xcode 7.0.

License

PKShortVideo is provided under the MIT license. See LICENSE file for details.

Contact

Weibo: @-湛藍_

Email: pepsikirk@gmail.com

中文介紹

這是一個類似微信小視頻功能的框架。
相關文章介紹:iOS仿微信小視頻功能開發優化記錄

sc1
sc1

特性

  • 小視頻聊天界面播放,使用基于 GPUImage 的 OpenGL ES 硬件加速播放視頻
  • 小視頻可以點擊放大播放,使用了 AVPlayer
  • 提供小視頻拍攝,能夠支持自定義分辨率視頻拍攝,有著基礎樣式,并提供了基礎的切換攝像頭、錄制、播放、重新錄制的功能,使用了 AVCaptureSession + AVCaptureVideoDataOutput和AVCaptureAudioDataOutput直接輸出視頻

安裝

  1. 在 Podfile 中添加 pod 'PKShortVideo'。
  2. 執行 pod install 或 pod update。
  3. 導入 #import "PKShortVideo.h"。

簡單用法

視頻錄制時,OutputFilePath參數為錄制完成后輸出的視頻文件路徑,OutputSize是輸出視頻的分辨率

簡單使用自帶UI界面時,錄制視頻(PKRecordShortVideoViewController)

進入錄制界面

//跳轉默認錄制視頻ViewController
PKRecordShortVideoViewController *viewController = [[PKRecordShortVideoViewController alloc] initWithOutputFilePath:path outputSize:CGSizeMake(320, 240) themeColor:[UIColor colorWithRed:0/255.0 green:153/255.0 blue:255/255.0 alpha:1]];
//通過代理回調
viewController.delegate = self;
[self presentViewController:viewController animated:YES completion:nil];

錄制完成回調

#pragma mark - PKRecordShortVideoDelegate
//視頻拍攝完成輸出圖片
- (void)didFinishRecordingToOutputFilePath:(NSString *)outputFilePath {
    //自定義的生成小視頻聊天對象方法
    [self.demoData addShortVideoMediaMessageWithVideoPath:outputFilePath];
    //JSQMessagesViewController的完成發送滾動到底端方法
    [self finishSendingMessageAnimated:YES];
}

自定義UI時錄制時,錄制視頻(PKShortVideoRecorder)

創建錄制對象

//創建視頻錄制對象
self.recorder = [[PKShortVideoRecorder alloc] initWithOutputFilePath:self.outputFilePath outputSize:self.outputSize];
//通過代理回調
self.recorder.delegate = self;
//錄制時需要獲取預覽顯示的layer,根據情況設置layer屬性,顯示在自定義的界面上
AVCaptureVideoPreviewLayer *previewLayer = [self.recorder previewLayer];
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.frame = CGRectMake(0, 44, kScreenWidth, PKPreviewLayerHeight);
[self.view.layer insertSublayer:previewLayer atIndex:0];

開始預覽攝像頭工作

//開始預覽攝像頭工作
[self.recorder startRunning];

切換前后攝像頭

//切換前后攝像頭
[self.recorder swapFrontAndBackCameras];

開始錄制

//開始錄制視頻
[self.recorder startRecording];

停止錄制

//停止錄制
[self.recorder stopRecording];

視頻錄制成功回調

//視頻錄制結束回調
- (void)recorder:(PKShortVideoRecorder *)recorder didFinishRecordingToOutputFilePath:(NSString *)outputFilePath error:(NSError *)error {
//錄制成功返回路徑,錄制失敗返回錯誤對象
}

視頻播放時,OutputFilePath參數為錄制完成后輸出的視頻文件路徑,previewImage是視頻預覽圖

聊天界面播放(由于聊天框架不同,這里只用JSQMessagesViewController進行示范)

聊天對象創建

- (void)addShortVideoMediaMessageWithVideoPath:(NSString *)videoPath  playType:(PKPlayType)type {
    //PKShortVideoItem為遵循JSQMessagesViewController的規范創建的媒體(非文字)類型
    //previewImage參數為視頻的預覽圖片
    
    switch (type) {
        case PKPlayTypeOpenGL: {
            PKShortVideoItem *videoItem = [[PKShortVideoItem alloc] initWithVideoPath:videoPath previewImage:[UIImage pk_previewImageWithVideoURL:[NSURL fileURLWithPath:videoPath]]];
            //創建message對象
            JSQMessage *videoMessage = [JSQMessage messageWithSenderId:kJSQDemoAvatarIdSquires
                                                           displayName:kJSQDemoAvatarDisplayNameSquires
                                                                 media:videoItem];
            //把創建聊天對象加入聊天數組
            [self.messages addObject:videoMessage];
        }
            break;
            
        case PKPlayTypeAVPlayer: {
            PKShortVideoItem2 *videoItem = [[PKShortVideoItem2 alloc] initWithVideoPath:videoPath previewImage:[UIImage pk_previewImageWithVideoURL:[NSURL fileURLWithPath:videoPath]]];
            //創建message對象
            JSQMessage *videoMessage = [JSQMessage messageWithSenderId:kJSQDemoAvatarIdSquires
                                                           displayName:kJSQDemoAvatarDisplayNameSquires
                                                                 media:videoItem];
            //把創建聊天對象加入聊天數組
            [self.messages addObject:videoMessage];
        }
            break;
    }

}

聊天對象附屬的媒體對象內部實現

可以使用基于 OpenGL 的 PKChatMessagePlayerView 和基于 AVPlayer 的 PKPlayerView ,由于 PKChatMessagePlayerView 實現的 OpenGL 的實現通過反映目前并不穩定,推薦使用 PKPlayerView ,使用接口完全一致。

//當前尺寸
CGSize size = [self mediaViewDisplaySize];
//實例化播放view
self.playerView = [[PKPlayerView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height) videoPath:self.videoPath previewImage:self.image];

如果需求策略非常復雜,如需判斷是群還是好友、各種網絡情況下,是否下載或者自動播放,仍然需要自定義聊天對象附屬媒體對象,PKChatMessagePlayerView僅可在視頻存在情況下播放使用

//開始播放小視頻
- (void)play {
    [self.playerView play];
}
//結束播放視頻
- (void)pause {
    [self.playerView stop];
}

聊天界面控制實現

出于性能考慮,最好在聊天界面處理做到顯示的時候才播放,不顯示的時候停止播放

//將要結束顯示時停止播放
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    JSQMessage *message = self.demoData.messages[indexPath.item];
    if ([message.media isKindOfClass:[PKShortVideoItem class]]) {
        PKShortVideoItem *item = (PKShortVideoItem *)message.media;
        [item pause];
    }
}

//將要顯示時播放
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    JSQMessage *message = self.demoData.messages[indexPath.item];
    if ([message.media isKindOfClass:[PKShortVideoItem class]]) {
        PKShortVideoItem *item = (PKShortVideoItem *)message.media;
        [item play];
    }
}

點擊全屏播放

//點擊消息是跳轉播放
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath {
    JSQMessage *message = self.demoData.messages[indexPath.item];
    //判斷媒體消息類型
    if ([message.media isKindOfClass:[PKShortVideoItem class]]) {
        PKShortVideoItem *item = (PKShortVideoItem *)message.media;
        //跳轉全屏播放小視頻界面
        PKFullScreenPlayerViewController *viewController = [[PKFullScreenPlayerViewController alloc] initWithVideoPath:item.videoPath previewImage:[UIImage pk_previewImageWithVideoURL:[NSURL fileURLWithPath:item.videoPath]]];
        [self presentViewController:viewController animated:NO completion:NULL];
    }
}

要求

本框架最低支持 iOS 7.0Xcode 7.0

許可證

PKShortVideo 使用 MIT 許可證,詳情見 LICENSE 文件。

聯系方式

Weibo: @-湛藍_

Email: pepsikirk@gmail.com

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容