【问题标题】:Why AVPlayer not stopping on the last frame of HLS streamed video?为什么 AVPlayer 不会在 HLS 流视频的最后一帧停止?
【发布时间】:2013-07-05 21:16:07
【问题描述】:

我以前用stitchedStreamPlayer 播放流视频。但是,我无法在视频的最后一帧停止。它显示黑屏。我设置属性

[player setActionAtItemEnd:AVPlayerActionAtItemEndPause];

仍然没有在最后一帧停止视频。我应该如何在最后一帧停止?

【问题讨论】:

  • 你有想过这个吗?
  • 我也遇到了同样的问题,有什么解决办法吗?谢谢。

标签: ios objective-c video-streaming avplayer


【解决方案1】:

这个问题似乎是由较长的音轨引起的。 下面的脚本修复了最后一个 .ts 文件。

last_ts=$(ls -1 "$dir"/out_*.ts | sort | tail -1)
bak=$last_ts.bak
filename="${last_ts##*/}"
basename="${filename%.*}"
workdir=/tmp

# copy only on the first run
[ -f "$bak" ] || cp -r "$last_ts" "$bak"

ffmpeg -y -i "$bak" -vn -c:a copy "$workdir/${basename}_a.ts"

video_stream_info="$(ffprobe "$bak" 2>&1 | grep 'Stream #0:0')"
resolution=$(echo "$video_stream_info" | perl -pe 's/^.*?, ([0-9]*x[0-9]*).*$/\1/g')
fps=$(echo "$video_stream_info" | perl -pe 's/^.*?([0-9.]*) fps.*$/\1/g')
bitrate=""
# FIXME
if [ $quality = low ];then
    bitrate=400k
elif [ $quality = mid ];then
    bitrate=900k
elif [ $quality = high ];then
    bitrate=1200k
fi
extended_duration=$(ffprobe "$bak" 2>&1 | perl -ne '/Duration: (\d*):(\d*):(\d*)\.(\d*)/ && print((((((int($1) * 60) + int($2)) * 60) + int($3)) * 100 + int($4) + 10)/100)')

ffmpeg -y -f lavfi -i nullsrc=s=${resolution}:d=${extended_duration}:r=${fps} -i "$bak" \
       -filter_complex "[0:v][1:v]overlay[video]" -map "[video]" \
       -b:v $bitrate -c:v libx264 -an "$workdir/${basename}_v.ts"

ffmpeg -y -i "$workdir/${basename}_v.ts" -i "$workdir/${basename}_a.ts" \
       -c:a copy -c:v copy \
       "$last_ts"

【讨论】:

  • 在我的情况下,音频轨道肯定比我上一个.ts 中的视频轨道短,但它仍然没有显示最后一帧
【解决方案2】:

我在这上面花了很多时间 ? 我确认我的视频轨道比音频轨道长,但它仍然没有停在最后一帧。不过,我想出了一个可怕的技巧来完成这项工作:

// Store as an instance variable so your observation sticks around
private var timeObservation: Any?

override func viewDidLoad() {
    super.viewDidLoad()

    timeObservation = player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
        self?.updateTime(time)
    }
}

private func updateTime(_ time: CMTime) {
    guard let item = player.currentItem else {
        return
    }

    // Assuming the video is 30fps and subtracting two frames. One wasn't enough for me.
    let offset = CMTime(seconds: 2 / 30, preferredTimescale: CMTimeScale(NSEC_PER_SEC))

    // If it's about to play past the end minus our offset, just stop
    if time >= item.duration - offset {
        player.pause()
        player.seek(to: item.duration - offset)
        return
    }
}
我尝试过的其他事情

在我开始使用 HLS 之前,我仍然无法让它在最后一帧暂停,而是使用 AVAssetImageGenerator 来获取最后一帧并在图像视图中显示它。这看起来有点跳动,压缩/颜色看起来从播放视频到缩略图不同。

我还看到了一些方法,您可以将输出添加到播放器,然后使用它来制作图像。我考虑过在最后尝试这样做,但我认为当你检测到需要图像时停止会容易得多。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 2020-02-29
    • 1970-01-01
    相关资源
    最近更新 更多