Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 40 additions & 27 deletions ICGVideoTrimmer/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15A284" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="vXZ-lx-hvc">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="NO" initialViewController="vXZ-lx-hvc">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
<development version="7000" identifier="xcode"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
</dependencies>
<scenes>
<!--View Controller-->
Expand All @@ -17,16 +18,14 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GF0-OD-nYr" userLabel="View - Player">
<rect key="frame" x="0.0" y="118" width="600" height="351"/>
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GF0-OD-nYr" userLabel="View - Player">
<rect key="frame" x="0.0" y="118" width="375" height="418"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NFN-te-fPQ" userLabel="View - Video Layer">
<rect key="frame" x="0.0" y="0.0" width="600" height="351"/>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NFN-te-fPQ" userLabel="View - Video Layer">
<rect key="frame" x="0.0" y="0.0" width="375" height="418"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="calibratedRGB"/>
</view>
</subviews>
<animations/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="NFN-te-fPQ" secondAttribute="trailing" id="2G7-Vz-3yC"/>
Expand All @@ -35,62 +34,76 @@
<constraint firstItem="NFN-te-fPQ" firstAttribute="top" secondItem="GF0-OD-nYr" secondAttribute="top" id="j4F-s2-rdZ"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="orR-Nb-icn" customClass="ICGVideoTrimmerView">
<rect key="frame" x="0.0" y="500" width="600" height="100"/>
<animations/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="orR-Nb-icn" customClass="ICGVideoTrimmerView">
<rect key="frame" x="0.0" y="567" width="375" height="100"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="x4j-N3-Ar5"/>
</constraints>
</view>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dww-6T-6Dy">
<rect key="frame" x="250" y="80" width="100" height="30"/>
<animations/>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dww-6T-6Dy">
<rect key="frame" x="255" y="80" width="100" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="BnU-Fb-06e"/>
<constraint firstAttribute="width" constant="100" id="kvn-MV-Jue"/>
</constraints>
<state key="normal" title="Trim it!">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="calibratedRGB"/>
</state>
<connections>
<action selector="trimVideo:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="X4Z-ys-lkT"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ro0-7V-UNL">
<rect key="frame" x="223" y="40" width="154" height="30"/>
<animations/>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gQR-Cf-JNR">
<rect key="frame" x="20" y="80" width="113" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="113" id="3M2-Y6-wTf"/>
<constraint firstAttribute="height" constant="30" id="j0n-F9-6gE"/>
</constraints>
<state key="normal" title="Change position">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="calibratedRGB"/>
</state>
<connections>
<action selector="changeTrimPosition:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="ccR-f2-OXa"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ro0-7V-UNL">
<rect key="frame" x="111" y="40" width="154" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="01F-h7-tCe"/>
<constraint firstAttribute="width" constant="154" id="cuP-7i-zQn"/>
</constraints>
<state key="normal" title="Select Asset">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="calibratedRGB"/>
</state>
<connections>
<action selector="selectAsset:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="7gP-Di-J1R"/>
</connections>
</button>
</subviews>
<animations/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstItem="2fi-mo-0CV" firstAttribute="top" secondItem="orR-Nb-icn" secondAttribute="bottom" id="0iP-7R-9tu"/>
<constraint firstItem="orR-Nb-icn" firstAttribute="top" secondItem="GF0-OD-nYr" secondAttribute="bottom" constant="31" id="1RM-Kb-sIa"/>
<constraint firstAttribute="trailing" secondItem="orR-Nb-icn" secondAttribute="trailing" id="6fS-lf-SuO"/>
<constraint firstItem="orR-Nb-icn" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="6ic-Sp-VaJ"/>
<constraint firstItem="dww-6T-6Dy" firstAttribute="centerX" secondItem="kh9-bI-dsS" secondAttribute="centerX" id="AY5-sQ-iFG"/>
<constraint firstItem="GF0-OD-nYr" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="Atf-cu-6DT"/>
<constraint firstItem="Ro0-7V-UNL" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" constant="20" id="BML-vX-hZT"/>
<constraint firstAttribute="trailing" secondItem="GF0-OD-nYr" secondAttribute="trailing" id="DOv-fl-TfK"/>
<constraint firstItem="gQR-Cf-JNR" firstAttribute="top" secondItem="Ro0-7V-UNL" secondAttribute="bottom" constant="10" id="NER-Q5-N42"/>
<constraint firstItem="GF0-OD-nYr" firstAttribute="top" secondItem="gQR-Cf-JNR" secondAttribute="bottom" constant="8" id="TrJ-iX-SBT"/>
<constraint firstItem="GF0-OD-nYr" firstAttribute="top" secondItem="dww-6T-6Dy" secondAttribute="bottom" constant="8" id="WQy-NZ-Tpa"/>
<constraint firstAttribute="trailing" secondItem="dww-6T-6Dy" secondAttribute="trailing" constant="20" id="e6s-Or-l6q"/>
<constraint firstItem="gQR-Cf-JNR" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" constant="20" id="loy-Ww-ygG"/>
<constraint firstItem="Ro0-7V-UNL" firstAttribute="centerX" secondItem="kh9-bI-dsS" secondAttribute="centerX" id="tlA-kh-XWg"/>
<constraint firstItem="dww-6T-6Dy" firstAttribute="top" secondItem="Ro0-7V-UNL" secondAttribute="bottom" constant="10" id="ygP-ac-6lJ"/>
</constraints>
</view>
<connections>
<outlet property="changePositionButton" destination="gQR-Cf-JNR" id="5Ao-6s-IkT"/>
<outlet property="trimButton" destination="dww-6T-6Dy" id="8zz-VP-XIK"/>
<outlet property="trimmerView" destination="orR-Nb-icn" id="JAL-XW-gzL"/>
<outlet property="videoLayer" destination="NFN-te-fPQ" id="vT6-kQ-4A1"/>
Expand Down
38 changes: 38 additions & 0 deletions ICGVideoTrimmer/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ @interface ViewController () <UINavigationControllerDelegate, UIImagePickerContr

@property (weak, nonatomic) IBOutlet ICGVideoTrimmerView *trimmerView;
@property (weak, nonatomic) IBOutlet UIButton *trimButton;
@property (weak, nonatomic) IBOutlet UIButton *changePositionButton;

@property (weak, nonatomic) IBOutlet UIView *videoPlayer;
@property (weak, nonatomic) IBOutlet UIView *videoLayer;

Expand Down Expand Up @@ -110,6 +112,7 @@ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPicking
[self.trimmerView resetSubviews];

[self.trimButton setHidden:NO];
[self.changePositionButton setHidden:NO];
}


Expand Down Expand Up @@ -190,6 +193,41 @@ - (IBAction)trimVideo:(id)sender
}
}

- (IBAction)changeTrimPosition:(id)sender {
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Change position" message:@"You can change the trim position by manually entereing the start and end time" preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
[textField setPlaceholder:@"Start time"];
[textField setKeyboardType:UIKeyboardTypeDecimalPad];
}];
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
[textField setPlaceholder:@"End time"];
[textField setKeyboardType:UIKeyboardTypeDecimalPad];

}];

UIAlertAction * changeAction = [UIAlertAction actionWithTitle:@"Change" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSString * startTimeString = alert.textFields.firstObject.text;
NSString * endTimeString = alert.textFields.lastObject.text;
double startTime = 0, endTime = CMTimeGetSeconds(_asset.duration);
if([startTimeString length]>0)
startTime = [alert.textFields.firstObject.text doubleValue];
if([endTimeString length]>0)
endTime = [alert.textFields.lastObject.text doubleValue];

[_trimmerView setVideoBoundsToStartTime:startTime endTime:endTime];


}];

UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];

[alert addAction:changeAction];
[alert addAction:cancelAction];
[self presentViewController:alert animated:YES completion:nil];

}


- (void)video:(NSString*)videoPath didFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo {
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Video Saving Failed"
Expand Down
3 changes: 3 additions & 0 deletions Source/ICGVideoTrimmerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ NS_ASSUME_NONNULL_BEGIN

- (void)hideTracker:(BOOL)flag;

-(void)setVideoBoundsToStartTime:(CGFloat)startTime endTime:(CGFloat)endTime;


@end

NS_ASSUME_NONNULL_END
Expand Down
62 changes: 62 additions & 0 deletions Source/ICGVideoTrimmerView.m
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,68 @@ - (void)hideTracker:(BOOL)flag
}
}

-(void)setVideoBoundsToStartTime:(CGFloat)startTime endTime:(CGFloat)endTime
{
//Validating the inputs.
if(startTime < 0 || endTime < 0 || startTime>=endTime || endTime>CMTimeGetSeconds([self.asset duration]) || (endTime-startTime)<self.minLength || (endTime-startTime)>self.maxLength)
return;


float newLeftOverlayViewMidX = [self getMiddleXPointForLeftOverlayViewWithTime:startTime];
self.leftOverlayView.center = CGPointMake(newLeftOverlayViewMidX, self.leftOverlayView.center.y);

float newRightOverlayVideMidX = [self getMiddleXPointForRightOverlayViewWithTime:endTime];
self.rightOverlayView.center = CGPointMake(newRightOverlayVideMidX, self.rightOverlayView.center.y);

[self notifyDelegateOfDidChange];
}


-(float)getMiddleXPointForLeftOverlayViewWithTime:(float)time
{
CGFloat leftOverlayViewNewX = ((((self.scrollView.contentOffset.x -self.thumbWidth) / self.widthPerSecond) - time)* self.widthPerSecond)*-1 ;

CGFloat leftOverlayViewOldX = CGRectGetMaxX(self.leftOverlayView.frame);

int deltaX = leftOverlayViewNewX-leftOverlayViewOldX;
CGPoint center = _leftOverlayView.center;

CGFloat newLeftViewMidX = center.x += deltaX;;
CGFloat maxWidth = CGRectGetMinX(_rightOverlayView.frame) - (_minLength * _widthPerSecond);
CGFloat newLeftViewMinX = newLeftViewMidX - _overlayWidth/2;
if (newLeftViewMinX < _thumbWidth - _overlayWidth) {
newLeftViewMidX = _thumbWidth - _overlayWidth + _overlayWidth/2;
} else if (newLeftViewMinX + _overlayWidth > maxWidth) {
newLeftViewMidX = maxWidth - _overlayWidth / 2;
}
if (!self.trackerView.hidden && time != self.startTime) {
[self seekToTime:time];
}
return newLeftViewMidX;

}
-(float)getMiddleXPointForRightOverlayViewWithTime:(float)time
{
CGFloat rightOverlayViewNewX = ((((self.scrollView.contentOffset.x -self.thumbWidth) / self.widthPerSecond) - time)* self.widthPerSecond)*-1 ;

CGFloat rightOverlayViewOldX = CGRectGetMinX(self.rightOverlayView.frame);

int rightDeltaX = rightOverlayViewNewX - rightOverlayViewOldX;

CGPoint rightCenter = self.rightOverlayView.center;

CGFloat newRightViewMidX = rightCenter.x += rightDeltaX;
CGFloat minX = CGRectGetMaxX(self.leftOverlayView.frame) + self.minLength * self.widthPerSecond;
CGFloat maxX = CMTimeGetSeconds([self.asset duration]) <= self.maxLength + 0.5 ? CGRectGetMaxX(self.frameView.frame) : CGRectGetWidth(self.frame) - self.thumbWidth;
if (newRightViewMidX - self.overlayWidth/2 < minX) {
newRightViewMidX = minX + self.overlayWidth/2;
} else if (newRightViewMidX - self.overlayWidth/2 > maxX) {
newRightViewMidX = maxX + self.overlayWidth/2;
}

return newRightViewMidX;
}

- (void)notifyDelegateOfDidChange
{
NSLog(@"leftOverlayView:%f , rightOverlayView:%f contentOffset.x:%@", CGRectGetMaxX(self.leftOverlayView.frame) , CGRectGetMaxX(self.rightOverlayView.frame) , @(self.scrollView.contentOffset.x));
Expand Down