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

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>.
- Add pod 'PKShortVideo' to your Podfile.
- Run pod install or pod update.
- 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仿微信小視頻功能開發優化記錄

特性
- 小視頻聊天界面播放,使用基于 GPUImage 的 OpenGL ES 硬件加速播放視頻
- 小視頻可以點擊放大播放,使用了 AVPlayer
- 提供小視頻拍攝,能夠支持自定義分辨率視頻拍攝,有著基礎樣式,并提供了基礎的切換攝像頭、錄制、播放、重新錄制的功能,使用了 AVCaptureSession + AVCaptureVideoDataOutput和AVCaptureAudioDataOutput直接輸出視頻
安裝
- 在 Podfile 中添加 pod 'PKShortVideo'。
- 執行 pod install 或 pod update。
- 導入 #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.0
和 Xcode 7.0
。
許可證
PKShortVideo 使用 MIT 許可證,詳情見 LICENSE 文件。
聯系方式
Weibo: @-湛藍_
Email: pepsikirk@gmail.com