Display a thumbnail of a locally recorded video?

If I use the video recording API to take a video, how could get I get a thumbnail from that?

2 Likes

This is also not possible currently :disappointed:

how would one do it natively in a detached app

1 Like

@waltershub
Here are somethings to consider in regards to this issue:

iOS only - not pro enough at Android

  • Say we were to get videos through the CameraRoll API that React Native provides as opposed to through some arbitrary file:// uri.
    1. React Native CameraRoll is pretty bad and uses outdated API (at least on the iOS side)
    2. The lame ALAsset API doesn’t have a thumbnail feature for videos, whereas PHAssets has something close

One method of getting thumbnails is through the AVAsset API but there are no instances of copyCGImageAtTime in Expo or RN

// https://stackoverflow.com/questions/31262606/how-to-get-thumbnail-image-of-video-from-alasset-in-ios/31262812
-(UIImage *)generateThumbImage : (NSString *)filepath
{
    NSURL *url = [NSURL fileURLWithPath:filepath];

    AVAsset *asset = [AVAsset assetWithURL:url];
    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
self.imageGenerator.appliesPreferredTrackTransform = YES; 
        CMTime time = [asset duration];
        time.value = 0;
        Float duration = CMTimeGetSeconds([myAsset duration]);
   for(Float i = 0.0; i<duration; i=i+0.1)
    {
     CGImageRef imgRef = [self.imageGenerator copyCGImageAtTime:CMTimeMake(i, duration) actualTime:NULL error:nil];
     UIImage* thumbnail = [[UIImage alloc] initWithCGImage:imgRef scale:UIViewContentModeScaleAspectFit orientation:UIImageOrientationUp];
    [thumbnailImages addObject:thumbnail];
    }
}

Another approach would be to load a video texture in a headless GL context and save copy of the buffer. Video Textures aren’t supported, and this method is suboptimal.

One could also use the MPMoviePlayer API. But it looks like this is also not in Expo or RN

NSString *str = [[self.videoArray objectAtIndex:i] valueForKey:@"vName"];
NSURL *videoURL = [NSURL URLWithString:str] ;
MPMoviePlayerController *player = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL]autorelease];
UIImage  *thumbnail = [player thumbnailImageAtTime:0.41 timeOption:MPMovieTimeOptionNearestKeyFrame];
player = nil;

Unless I’m missing something I think I figured it out, it was so obvious, you just wrap video component with playing and controls set to false in a touchable opacity like this. I know this is not technically an image thumbnail but practically its the same thing

<TouchableOpacity
    onPress={() => this.props.navigation.navigate('Player', { video: video.video.uri })}
    style={{ height: 200, width: 200, marginBottom: 20 }}
    key={uniqueId()}>
     <Video
        style={{ height: 200, width: 200 }}
        source={{ uri: video.video.uri }}
        usePoster
        shouldPlay={false}
     />
</TouchableOpacity>
2 Likes

I like it <33đź’™definitely would work for poster images.

In theory the most common reason you would need a thumbnail would be for scrolling through your camera roll. In that case you would wan’t something really fast, I can’t say for certain but loading all videos into memory is very expensive.

To me whats weird about this whole thing is that when the video is not playing isn’t the phone technically rendering an image, why isn’t there a way just to grab that, isn’t the use poster prop technically doing that, why isn’t there a way to return it to me

1 Like

The poster prop is actually accepting some random image. Technically you could snapshot the video when it is paused. This would all run on the main thread and could bog down the js.

ya but its a random image from the video(i don’t understand at all how videos load so forgive my ignorance ), couldn’t there be a way of calling that poster prop as a stand alone function without loading the whole image or in the record video options couldnt there be an option to videoThumb which would return a poster. something like this

<Image source={generatePoster(videoUri)} />
1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.