AVMutableComposition精确计时 [英] precise timing with AVMutableComposition

查看:88
本文介绍了AVMutableComposition精确计时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用AVMutableComposition在精确的时间播放一系列声音文件.

I'm trying to use AVMutableComposition to play a sequence of sound files at precise times.

在加载视图时,我创建的合成是要播放1秒内均匀分布的4种声音.声音的时间长短无关紧要,我只想在0、0.25、0.5和0.75秒时发射它们:

When the view loads, I create the composition with the intent of playing 4 sounds evenly spaced over 1 second. It shouldn't matter how long or short the sounds are, I just want to fire them at exactly 0, 0.25, 0.5 and 0.75 seconds:

AVMutableComposition *composition = [[AVMutableComposition alloc] init];
NSDictionary *options = @{AVURLAssetPreferPreciseDurationAndTimingKey : @YES};

for (NSInteger i = 0; i < 4; i++)
{
  AVMutableCompositionTrack* track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
  NSURL *url = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:@"sound_file_%i", i] withExtension:@"caf"];
  AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:options];
  AVAssetTrack *assetTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;
  CMTimeRange timeRange = [assetTrack timeRange];
  Float64 t = i * 0.25;
  NSError *error;
  BOOL success = [track insertTimeRange:timeRange ofTrack:assetTrack atTime:CMTimeMakeWithSeconds(t, 1) error:&error];
  if (!success)
  {
    NSLog(@"unsuccesful creation of composition");
  }
  if (error)
  {
    NSLog(@"composition creation error: %@", error);
  }
}

AVPlayerItem* playerItem = [AVPlayerItem playerItemWithAsset:composition];
self.avPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem];

合成成功创建,没有错误.稍后,当我要播放音序时,我会执行以下操作:

The composition is created successfully with no errors. Later, when I want to play the sequence I do this:

[self.avPlayer seekToTime:CMTimeMakeWithSeconds(0, 1)];
[self.avPlayer play];

由于某种原因,声音的间隔根本不是均匀的-而是几乎同时播放.我尝试了间隔4秒的相同内容,替换了像这样的时间计算:

For some reason, the sounds are not evenly spaced at all - but play almost all at once. I tried the same thing spaced over 4 seconds, replacing the time calculation like this:

Float64 t = i * 1.0;

这玩起来很完美. 1秒以下的任何时间间隔似乎都会产生意外结果.我想念什么? AVComposition是否不应该用于1秒以下的时间间隔?还是我误会了时间间隔?

And this plays perfectly. Any time interval under 1 second seems to generate unexpected results. What am I missing? Are AVCompositions not supposed to be used for time intervals under 1 second? Or perhaps I'm misunderstanding the time intervals?

推荐答案

您的CMTimeMakeWithSeconds(t, 1)整整是第二个切片",因为您的时间刻度设置为1.无论t是多少,atTime:始终最终为0.这就是为什么将其增加到1秒(t = i * 1)时起作用的原因.

Your CMTimeMakeWithSeconds(t, 1) is in whole second 'slices' because your timescale is set to 1. No matter what fraction t is, the atTime: will always end up as 0. This is why it works when you increase it to 1 second (t=i*1).

您需要将时间刻度设置为4,以获得所需的0.25秒切片.由于CMTime现在处于.25秒切片中,因此您不需要i * 0.25计算.只需直接使用i即可; atTime:CMTimeMake(i, 4)

You need to set the timescale to 4 to get your desired 0.25 second slices. Since the CMTime is now in .25 second slices, you won't need the i * 0.25 calculcation. Just use the i directly; atTime:CMTimeMake(i, 4)

如果将来可能需要更精确一些,则应立即说明,以便以后不必调整代码. Apple建议使用600的时间刻度,因为它是常见视频帧速率(24、25和30 FPS)的倍数,但它也仅适用于音频.因此,对于您的情况,您将使用24个slice来获得.25秒的值; Float64 t = i * 24; atTime:CMTimeMake(t, 600)

If you might need to get more precise in the future, you should account for it now so you won't have to adjust your code later. Apple recommends using a timescale of 600 as it is a multiple of the common video framerates (24, 25, and 30 FPS) but it works fine for audio-only too. So for your situation, you would use 24 slices to get your .25 second value; Float64 t = i * 24; atTime:CMTimeMake(t, 600)

关于几乎同时播放所有4种声音的问题,请注意

As for your issue of all 4 sounds playing almost all at once, be aware of this unanswered SO question where it only happens on the first play. Even with the changes above, you might still run into this issue.

这篇关于AVMutableComposition精确计时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆