我正在尝试制作一个简单的HLS播放器来控制播放并在辅助监视器上显示.我在10.7中使用AVFoundation来控制播放.我可以成功创建AVPlayerItem和AVPlayer,但我实际上遇到了在NSView中显示视频的问题.
我必须承认我是Cocoa新手,并且来自iOS开发,所以我可能会遗漏一些简单的东西.然而,我花了4-5个小时试图让它工作,我没有成功.
当我从AVPlayer播放视频时,播放开始,我可以听到音频.但是,没有视频出现.
我试图让它变得尽可能简单.我有一个NSViewController,我在其中添加了一个AVPlayerLayer的视图层:
AVPlayerLayer * playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
[playerLayer setFrame:self.view.bounds];
[self.view.layer addSublayer:playerLayer];
Run Code Online (Sandbox Code Playgroud)
据我所知,这就是我所要做的.但是,视频永远不会出现在视图中.
有没有人成功将AVPlayerLayer添加到NSView?AVFoundation文档显示了如何使用UIView完成此操作,并且我已经尝试过该方法,但在NSView中没有运气.
任何帮助将不胜感激!
我正在尝试做一个基本的无线电应用程序,我得到了一个URL列表:当我尝试调用无效的URL(错误的路径或没有可播放文件的正确路径)时,Observer似乎永远不会被调用.这是我的代码的一部分:
urlStream = [NSURL URLWithString:mp3URL];
self.playerItem = [AVPlayerItem playerItemWithURL:urlStream];
[playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
[appDelegate.player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
[appDelegate.player replaceCurrentItemWithPlayerItem:playerItem]; //OK
[appDelegate.player play];
Run Code Online (Sandbox Code Playgroud)
在我得到的相对观察者方法中:
if (object == playerItem && [keyPath isEqualToString:@"playbackBufferEmpty"])
{
if (playerItem.playbackBufferEmpty)
{
NSLog(@"playbackBufferEmpty");
[self alertBuffer];
}
}
if (object == playerItem && [keyPath isEqualToString:@"playbackLikelyToKeepUp"])
{
if (playerItem.playbackLikelyToKeepUp)
{
NSLog(@"playbackLikelyToKeepUp");
[loadStation stopAnimating];
if (playerItem.status == AVPlayerItemStatusReadyToPlay) {
NSLog(@"AVPlayerItemStatusReadyToPlay");
}
else if (playerItem.status == AVPlayerStatusFailed) {
NSLog(@"AVPlayerStatusFailed");
}
else if (playerItem.status == AVPlayerStatusUnknown) …Run Code Online (Sandbox Code Playgroud) 我有用于显示AVPlayer播放的PlayerView类.文档代码.
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface PlayerView : UIView
@property (nonatomic) AVPlayer *player;
@end
@implementation PlayerView
+ (Class)layerClass {
return [AVPlayerLayer class];
}
- (AVPlayer*)player {
return [(AVPlayerLayer *)[self layer] player];
}
- (void)setPlayer:(AVPlayer *)player {
[(AVPlayerLayer *)[self layer] setPlayer:player];
}
@end
Run Code Online (Sandbox Code Playgroud)
我在此PlayerView中设置了我的AVPlayer(包含大小为320x240的视频资产)(frame.size.width = 100,frame.size.height = 100)并调整了我的视频大小.添加PlayerView后如何获得视频大小?
我正在使用iOS AVPlayer播放HLS流.在HLS会话开始时,当我收到index.m3u8 URL以响应创建AVPlayerItem时,响应还会设置基于会话的身份验证所需的cookie.假设这个cookie名称是myCookie,它是为域".myhost.com"创建的.现在一切正常,播放器发送myCookie从xxx.myhost.com/stream下载ts块.随着播放的进行,播放列表最终会更新,播放器会下载更新的播放列表.有时,更新的播放列表包含从其他主机的URL下载的ts块.因此,当尝试使用不同的主机播放块时,播放器请求xxx.someotherhost.com下载块.这导致响应302重定向与位置:xxx-abc.myhost.com/ads.显然AVPlayer没有 从someotherhost.com请求一个块时发送myCookie,因为它与myCookie的域不匹配.但问题是在重定向到xxx-abc.myhost.com/ads后,AVPlayer不发送myCookie,即使重定向URL的域名也是myhost.com,也与cookie的域匹配.
请注意,重定向URL域与原始流域相同,也与myCookie域相同.由于AVPlayer在重定向后没有将cookie发送到下载块,因此ts块请求失败,403 Forbidden(No Token)
我在这里做错了什么,或者这看起来像iOS AVPlayer中的错误?
有没有办法解决这个问题?请分享你的想法.
我有兴趣在iOS中使用AVCaptureSession录制媒体,同时使用AVPlayer播放媒体(具体来说,我正在播放音频和录制视频,但我不确定这是否重要).
问题是,当我稍后将结果媒体重新播放时,它们会不同步.是否可以通过确保同时开始播放和录制,或通过发现它们之间的偏移来同步它们?我可能需要同步大约10毫秒.假设我总能捕获音频(因为用户可能使用耳机)是不合理的,因此通过分析原始和录制的音频进行同步不是一种选择.
这个问题表明,可以同时结束播放和录制并从那里确定最终偏移的初始偏移,但我不清楚如何让它们同时结束.我有两种情况:1)音频播放耗尽,2),用户点击"停止录制"按钮.
这个问题建议启动,然后应用一个固定的,但可能依赖于设备的延迟,这显然是一个黑客,但如果它对音频足够好,显然值得考虑视频.
我可以使用另一个媒体层来执行所需的同步吗?
相关:这个问题没有答案.
当你播放远程视频AVPlayer并开始倒带时,擦洗器就会出现问题.
如何顺利实施?
我项目的代码如下 - https://github.com/nullproduction/Player
- (void)initScrubberTimer
{
double interval = .1f;
CMTime playerDuration = [self playerItemDuration];
if (CMTIME_IS_INVALID(playerDuration))
{
return;
}
double duration = CMTimeGetSeconds(playerDuration);
if (isfinite(duration))
{
CGFloat width = CGRectGetWidth([scrubberSlider bounds]);
interval = 0.5f * duration / width;
}
__weak id weakSelf = self;
CMTime intervalSeconds = CMTimeMakeWithSeconds(interval, NSEC_PER_SEC);
mTimeObserver = [self.player addPeriodicTimeObserverForInterval:intervalSeconds
queue:dispatch_get_main_queue()
usingBlock:^(CMTime time) {
[weakSelf syncScrubber];
}];
}
- (void)syncScrubber
{
CMTime playerDuration = [self playerItemDuration];
if (CMTIME_IS_INVALID(playerDuration)) …Run Code Online (Sandbox Code Playgroud) 有时AVPlayer失败,AVPlayerItemStatusFailed并且在失败发生后,AVPlayer继续失败AVPlayerItemStatusFailed.我试图清除AVPlayer实例并创建新实例,但我无法实现AVPlayerItemStatusFailed无法解决.也removingFromSuperview UIView有AVPlayer实例和初始化新项目与AVPlayer不会解决问题.
所以我认为AVPlayer无法完全清除.是否有人建议完全清除AVPlayer并使其在失败后工作?
错误日志:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x1a689360 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x1a688e70 "The operation couldn’t be completed. (OSStatus error -12983.)", NSLocalizedFailureReason=An unknown error occurred (-12983)}
Run Code Online (Sandbox Code Playgroud)
UPD. 对于@matt
playerItem = [AVPlayerItem playerItemWithURL:[NSURL fileURLWithPath:filePath.path]];
if (!self.avPlayer) {
avPlayer = [AVPlayer playerWithPlayerItem:playerItem];
}
[avPlayer.currentItem addObserver:self forKeyPath:@"status" options:0 context:nil];
if (self.avPlayer.currentItem != self.playerItem) {
[self.avPlayer replaceCurrentItemWithPlayerItem:playerItem];
}
AVPlayerLayer *avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:avPlayer];
avPlayerLayer.frame = self.bounds;
[self.layer addSublayer:avPlayerLayer]; …Run Code Online (Sandbox Code Playgroud) 似乎api replaceCurrentItemWithPlayerItem:将主线程卡住几秒钟,我明白更换项目需要新项目的信息,这可能需要一些时间来预加载.但是问题出现了,为什么replaceCurrentItemWithPlayerItem:用一个nil项目对象也会卡住主线程?在我看来,有时需要超过5秒的时间才能替换nil playerItem.我想知道如何避免这个问题.谢谢你的任何建议!
使用AVPlayer播放远程视频时,我遇到了一个奇怪的崩溃.从Fabric上的崩溃日志开始,应用程序在系统线程上崩溃(com.apple.avfoundation.playerlayer.configuration).崩溃日志如下:
Crashed: com.apple.avfoundation.playerlayer.configuration
0 libsystem_kernel.dylib 0x1839ac2e8 __pthread_kill + 8
1 libsystem_pthread.dylib 0x183ac12f8 pthread_kill$VARIANT$mp + 396
2 libsystem_c.dylib 0x18391afbc abort + 140
3 libsystem_malloc.dylib 0x1839e3ce4 szone_size + 634
4 QuartzCore 0x187ed75e8 -[CALayer dealloc] + 72
5 QuartzCore 0x187e75d90 CA::Transaction::commit() + 1052
6 AVFoundation 0x18973b4a8 -[AVPlayerLayer observeValueForKeyPath:ofObject:change:context:] + 684
7 Foundation 0x1847a2894 NSKeyValueNotifyObserver + 304
8 Foundation 0x1847bc364 -[NSObject(NSKeyValueObserverRegistration) _addObserver:forProperty:options:context:] + 204
9 Foundation 0x1847bc13c -[NSObject(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:] + 124
10 AVFoundation 0x189760714 -[AVPlayer addObserver:forKeyPath:options:context:] + 204 …Run Code Online (Sandbox Code Playgroud) 有没有办法在AVPlayer中播放音频之前截取字节数据并对每个字节执行XOR操作?
我正在构建一个音频流应用程序,并使用一个用C编写的小脚本向MP3文件添加简单的加密层。在Android中,它会像这样实时解码:
@Override
public int read(byte[] buffer, int offset, int readLength) throws FileDataSourceException {
// ...
if (readLength == 1 && offset >= 1 && offset <= 123) {
buffer[offset] = (byte)(buffer[offset] ^ 11);
}
return bytesRead;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面看到的,在Android中反转XOR加密非常容易,因为我使用ExoPlayer并在其数据源类中覆盖read()方法。是否有机会在Swift中使用AVPlayer执行相同的操作?
这是整个想法的流程图:
谢谢。
avplayer ×10
ios ×8
avfoundation ×7
objective-c ×3
swift ×2
avplayeritem ×1
cocoa ×1
encryption ×1
nshttpcookie ×1
nsview ×1
osx-lion ×1
ui-thread ×1