如何从 Objective-C 中未显示的视频生成视频缩略图

问题描述 投票:0回答:2

对于 Objective-C 中的 iOS 项目,我需要显示屏幕上未显示的 rtsp 视频流的缩略图(我无法截图)。 我的视图显示一个视频流和其他流的三个缩略图(定期刷新),以便用户可以在它们之间切换。

那么,我怎样才能生成这个缩略图呢? 我正在使用 MobileVLCKit 来显示我的主视频流(如果可能的话,我更愿意使用这个框架来生成我的缩略图......)。

我在论坛和谷歌结果中找到了很多结果,但没有一个符合我的情况:流+不显示视频。

感谢您的帮助!

编辑:

我也尝试过VLC的缩略图,但没有成功:

VLCMedia *media = [VLCMedia mediaWithURL:[NSURL URLWithString:<Rtsp Url>]];
thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:media andDelegate:self];

但我总是陷入 mediaThumbnailerDidTimeOut 委托方法。

ios objective-c streaming vlc video-thumbnails
2个回答
0
投票

基本上您需要做的就是使用 VLCKit 'VLCMediaThumbnailer' 类并实现 'VLCMediaThumbnailerDelegate' 所需的两个函数

这是一个 Objective-C 示例

@implementation DummyObject <VLCMediaThumbnailerDelegate>

- (void)workerMethod
{
    NSURL *url = [NSURL urlWithString:@""];
    VLCMedia *media = [VLCMedia mediaWithURL:url];

    VLCMediaThumbnailer *thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:media delegate:self];

    CGSize thumbSize = CGSizeMake(800.,600.);
    thumbnailer.thumbnailWidth = thumbSize.width;
    thumbnailer.thumbnailHeight = thumbSize.height;

    [thumbnailer fetchThumbnail];
}

- (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail
{
    if (thumbnail) {
        UIImage *thumbnailImage = [UIImage imageWithCGImage:thumbnail scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
        if (thumbnailImage) {
            // do something with the thumbnail
        }
    }
}

- (void)mediaThumbnailerDidTimeOut:(VLCMediaThumbnailer *)mediaThumbnailer
{
     // show error generating thumbnail
}

@end

Objective-C 代码的学分

这就是它在 swift 和 SwiftUI 中的样子

func generateThumbnails()
{
    if mediaPlayer.media != nil
    {
        let vlcMediaThumbnailer: VLCMediaThumbnailer = VLCMediaThumbnailer(media: mediaPlayer.media, andDelegate: self)
        vlcMediaThumbnailer.thumbnailWidth = 440
        vlcMediaThumbnailer.thumbnailHeight = 225
        vlcMediaThumbnailer.snapshotPosition = 0.5 // get thumbs from the middle of the video

        vlcMediaThumbnailer.fetchThumbnail()
    }
}

func mediaThumbnailerDidTimeOut(_ mediaThumbnailer: VLCMediaThumbnailer!)
{
    print("failed generating thumbnail")
}

func mediaThumbnailer(_ mediaThumbnailer: VLCMediaThumbnailer!, didFinishThumbnail thumbnail: CGImage!)
{
    print("got another thumbnail - do something with it")
}

这里是 tvOS 14.7 和 SwiftUI 中的 apple-tv 的 完整工作演示,用于 VLCKit 中的 缩略图:

import SwiftUI import AVFoundation class VideoModel: ObservableObject { @Published var thumbnails: [Image] = [] var videoUrl: String = "" let thumbnailWidth: CGFloat = 400.0 let thumbnailHeight: CGFloat = 225.0 } struct VLCPlayerTestView: View { @State var isPlayVideo: Bool = false let videoUrl: String = "https://upload.wikimedia.org/wikipedia/commons/transcoded/c/c0/Big_Buck_Bunny_4K.webm/Big_Buck_Bunny_4K.webm.480p.vp9.webm" var videoPlayer: VideoPlayer? = nil @ObservedObject var videoModel = VideoModel() init() { videoModel.videoUrl = videoUrl videoPlayer = VideoPlayer(videoModel: videoModel) } var body: some View { HStack(spacing: 20) { ForEach(0..<videoModel.thumbnails.count, id: \.self) { itemIndex in videoModel.thumbnails[itemIndex] .resizable() .aspectRatio(contentMode: .fill) .frame(width: videoModel.thumbnailWidth, height: videoModel.thumbnailHeight, alignment: Alignment.center) .focusable() .onLongPressGesture(minimumDuration: 0.01) { isPlayVideo = true } } } .fullScreenCover(isPresented: $isPlayVideo) { videoPlayer .edgesIgnoringSafeArea(.all) .onAppear { videoPlayer!.player.playVideo() } .onDisappear { videoPlayer!.player.stopVideo() } } } } struct VideoPlayer: UIViewRepresentable { var player: VLCPlayerView init(videoModel: VideoModel) { player = VLCPlayerView() player.videoModel = videoModel player.loadMedia() player.generateThumbnails() } func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<VideoPlayer>) { } func makeUIView(context: Context) -> UIView { return player } } class VLCPlayerView: UIView, VLCMediaPlayerDelegate, VLCMediaThumbnailerDelegate { var videoModel: VideoModel? let mediaPlayer: VLCMediaPlayer = VLCMediaPlayer() override init(frame: CGRect) { super.init(frame: frame) } func loadMedia() { if !videoModel!.videoUrl.isEmpty { mediaPlayer.media = VLCMedia(url: URL(string: videoModel!.videoUrl)!) mediaPlayer.delegate = self mediaPlayer.drawable = self generateThumbnails() } } func playVideo() { if mediaPlayer.media != nil { mediaPlayer.play() } } func pauseVideo() { if mediaPlayer.media != nil && mediaPlayer.isPlaying { mediaPlayer.pause() } } func stopVideo() { if mediaPlayer.media != nil { mediaPlayer.stop() } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() } func generateThumbnails() { if mediaPlayer.media != nil { let vlcMediaThumbnailer: VLCMediaThumbnailer = VLCMediaThumbnailer(media: mediaPlayer.media, andDelegate: self) vlcMediaThumbnailer.thumbnailWidth = videoModel!.thumbnailWidth vlcMediaThumbnailer.thumbnailHeight = videoModel!.thumbnailHeight vlcMediaThumbnailer.snapshotPosition = 0.5 vlcMediaThumbnailer.fetchThumbnail() } } func mediaThumbnailerDidTimeOut(_ mediaThumbnailer: VLCMediaThumbnailer!) { print("failed generating thumbnail") } func mediaThumbnailer(_ mediaThumbnailer: VLCMediaThumbnailer!, didFinishThumbnail thumbnail: CGImage!) { print("got another thumbnail") if(thumbnail != nil) { let thumbnailUIImage = UIImage(cgImage: thumbnail) let image = Image(uiImage: thumbnailUIImage).renderingMode(.original) videoModel!.thumbnails.append(image) } } }
结果:


0
投票
大家下午好!

我尝试了自己的实现,但没有成功好几个小时,所以我看到了这篇文章。 总的来说,@Shaybc 提供的代码可以工作,但可以简化。

无论@Shaybc代码还是我的代码,我不明白为什么我不能生成指向不同位置的多个缩略图。

慢慢点击按钮会生成第一个缩略图,但其他缩略图会变黑。快速点击会使所有缩略图变黑。

如果有人有任何想法,我会接受!

import SwiftUI import AVFoundation import MobileVLCKit struct VLCPlayerTestView: View { let videoUrl: String = "https://upload.wikimedia.org/wikipedia/commons/transcoded/c/c0/Big_Buck_Bunny_4K.webm/Big_Buck_Bunny_4K.webm.480p.vp9.webm" @ObservedObject var container = ThumbnailerContainer() var body: some View { Button { container.generateThumbnail(urlString: videoUrl) } label: { Text("Generate Thumbnail") } ScrollView { VStack(spacing: 20) { ForEach(0..<container.thumbnails.count, id: \.self) { itemIndex in container.thumbnails[itemIndex] .resizable() .aspectRatio(contentMode: .fill) } } } } } class ThumbnailerContainer: ObservableObject { @Published var thumbnailers: [Thumbnailer] = [] @Published var thumbnails: [Image] = [] func generateThumbnail(urlString: String) -> Void { let thumbnailer = Thumbnailer(container: self) thumbnailer.generateThumbnail(urlString: urlString) thumbnailers.append(thumbnailer) } } class Thumbnailer: VLCMediaThumbnailerDelegate, ObservableObject { @Published var container: ThumbnailerContainer init(container: ThumbnailerContainer) { self.container = container } func generateThumbnail(urlString: String) { let media = VLCMedia(url: URL(string: urlString)!) let vlcMediaThumbnailer: VLCMediaThumbnailer = VLCMediaThumbnailer(media: media, andDelegate: self) vlcMediaThumbnailer.thumbnailWidth = 400 vlcMediaThumbnailer.thumbnailHeight = 225 vlcMediaThumbnailer.snapshotPosition = Float.random(in: 0...1) print("Fetching thumbnail for position \(vlcMediaThumbnailer.snapshotPosition)") vlcMediaThumbnailer.fetchThumbnail() } func mediaThumbnailerDidTimeOut(_ mediaThumbnailer: VLCMediaThumbnailer!) { print("failed generating thumbnail") } func mediaThumbnailer(_ mediaThumbnailer: VLCMediaThumbnailer!, didFinishThumbnail thumbnail: CGImage!) { print("Got a thumbnail for position \(mediaThumbnailer.snapshotPosition)") let thumbnailUIImage = UIImage(cgImage: thumbnail) let image = Image(uiImage: thumbnailUIImage).renderingMode(.original) container.thumbnails.append(image) } }
    
© www.soinside.com 2019 - 2024. All rights reserved.