rtmp、rtc推拉流支持加密
This commit is contained in:
@@ -27,6 +27,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// 视频编码器(H.264/H.265)
|
||||
@property (nonatomic, assign) AVVideoCodec codec;
|
||||
|
||||
/// XOR 加密密钥(十六进制字符串,如 @"AABBCCDD"),为空则不加密
|
||||
@property (nonatomic, copy, nullable) NSString *xorKey;
|
||||
|
||||
// ============ 工厂方法 ============
|
||||
|
||||
/// 创建默认配置
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
#import "TokenGenerator.h"
|
||||
#import "AVLiveStreamModel.h"
|
||||
#import "AVConstants.h"
|
||||
#import <AFNetworking/AFNetworking.h>
|
||||
#import <YYModel/YYModel.h>
|
||||
#import "AVApiService.h"
|
||||
|
||||
@interface SCLivePusherViewController ()<SellyLivePusherDelegate, SellyLivePlayerDelegate>
|
||||
@property (nonatomic, strong)UIView *liveView;
|
||||
@@ -196,6 +195,16 @@
|
||||
[AVConfigManager.sharedManager saveConfig];
|
||||
|
||||
if (!self.isLiveStarted) {
|
||||
// 校验加密密钥
|
||||
NSString *xorKeyError = [self validateXorKey:self.videoConfig.xorKey];
|
||||
if (xorKeyError) {
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"密钥格式错误"
|
||||
message:xorKeyError
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
return;
|
||||
}
|
||||
// 开始直播
|
||||
[self startLive];
|
||||
self.isLiveStarted = YES;
|
||||
@@ -449,7 +458,8 @@
|
||||
|
||||
NSString *token = [TokenGenerator generateStreamSignatureWithVhost:V_HOST appId:APP_ID channelId:self.videoConfig.streamId type:@"push" key:APP_SECRET];
|
||||
self.livePusher.token = token;
|
||||
|
||||
self.livePusher.xorKey = self.videoConfig.xorKey;
|
||||
|
||||
NSError *error;
|
||||
if (self.videoConfig.streamId) {
|
||||
error = [self.livePusher startLiveWithStreamId:self.videoConfig.streamId];
|
||||
@@ -460,6 +470,31 @@
|
||||
if (error) {
|
||||
NSLog(@"###startLive failed. error == %@",error.localizedDescription);
|
||||
}
|
||||
|
||||
// 上报 XOR key 到服务器
|
||||
[self reportXorKey];
|
||||
}
|
||||
|
||||
/// 校验 xorKey 格式,返回 nil 表示合法,返回错误信息表示不合法
|
||||
- (NSString *)validateXorKey:(NSString *)xorKey {
|
||||
if (xorKey.length == 0) return nil;
|
||||
if (xorKey.length % 2 != 0) {
|
||||
return @"加密密钥必须为偶数长度";
|
||||
}
|
||||
NSCharacterSet *hexChars = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"];
|
||||
if ([xorKey rangeOfCharacterFromSet:hexChars.invertedSet].location != NSNotFound) {
|
||||
return @"加密密钥只能包含十六进制字符 (0-9, a-f, A-F)";
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)reportXorKey {
|
||||
[[AVApiService shared] reportXorKeyWithVhost:V_HOST
|
||||
app:APP_ID
|
||||
stream:self.videoConfig.streamId
|
||||
xorKey:self.videoConfig.xorKey
|
||||
success:nil
|
||||
failure:nil];
|
||||
}
|
||||
|
||||
- (void)setupItemContainer {
|
||||
@@ -724,47 +759,27 @@
|
||||
[self presentViewController:loadingAlert animated:YES completion:nil];
|
||||
|
||||
// 获取直播列表
|
||||
AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];
|
||||
sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];
|
||||
sessionManager.requestSerializer.timeoutInterval = 10;
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
NSString *apiURL = @"http://rtmp.sellycloud.io:8089/live/sdk/alive-list";
|
||||
|
||||
[sessionManager GET:apiURL parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary *responseObject) {
|
||||
[[AVApiService shared] fetchLiveStreams:^(NSArray<AVLiveStreamModel *> *streams) {
|
||||
__strong typeof(weakSelf) strongSelf = weakSelf;
|
||||
if (!strongSelf) return;
|
||||
|
||||
// 关闭加载提示
|
||||
[loadingAlert dismissViewControllerAnimated:YES completion:^{
|
||||
// 解析数据
|
||||
NSArray<AVLiveStreamModel *> *liveStreams = [NSArray yy_modelArrayWithClass:AVLiveStreamModel.class json:responseObject[@"list"]];
|
||||
|
||||
NSLog(@"✅ 获取 %ld 个直播流", (long)liveStreams.count);
|
||||
|
||||
if (liveStreams.count == 0) {
|
||||
// 没有直播流
|
||||
if (streams.count == 0) {
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示"
|
||||
message:@"暂无正在直播的用户"
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
|
||||
[strongSelf presentViewController:alert animated:YES completion:nil];
|
||||
} else {
|
||||
// 显示直播流列表
|
||||
[strongSelf showStreamListWithStreams:liveStreams];
|
||||
[strongSelf showStreamListWithStreams:streams];
|
||||
}
|
||||
}];
|
||||
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
} failure:^(NSError *error) {
|
||||
__strong typeof(weakSelf) strongSelf = weakSelf;
|
||||
if (!strongSelf) return;
|
||||
|
||||
// 关闭加载提示
|
||||
[loadingAlert dismissViewControllerAnimated:YES completion:^{
|
||||
NSLog(@"❌ 获取直播列表失败: %@", error.localizedDescription);
|
||||
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"加载失败"
|
||||
message:[NSString stringWithFormat:@"无法获取直播列表: %@", error.localizedDescription]
|
||||
message:error.localizedDescription
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
|
||||
[strongSelf presentViewController:alert animated:YES completion:nil];
|
||||
|
||||
Reference in New Issue
Block a user