mod: dash格式视频播放、记忆播放
This commit is contained in:
@ -6,6 +6,7 @@ import 'package:pilipala/models/common/reply_type.dart';
|
||||
import 'package:pilipala/models/model_hot_video_item.dart';
|
||||
import 'package:pilipala/models/model_rec_video_item.dart';
|
||||
import 'package:pilipala/models/user/fav_folder.dart';
|
||||
import 'package:pilipala/models/video/play/url.dart';
|
||||
import 'package:pilipala/models/video_detail_res.dart';
|
||||
|
||||
/// res.data['code'] == 0 请求正常返回结果
|
||||
@ -66,8 +67,9 @@ class VideoHttp {
|
||||
'avid': avid,
|
||||
// 'bvid': bvid,
|
||||
'cid': cid,
|
||||
'qn': qn ?? 64,
|
||||
// 'fnval': 16,
|
||||
// 'qn': qn ?? 80,
|
||||
// 获取所有格式的视频
|
||||
'fnval': 4048,
|
||||
// 'fnver': '',
|
||||
'fourk': 1,
|
||||
// 'session': '',
|
||||
@ -83,7 +85,10 @@ class VideoHttp {
|
||||
// for (var i in res.data['data']['list']) {
|
||||
// list.add(HotVideoItemModel.fromJson(i));
|
||||
// }
|
||||
return {'status': true, 'data': res.data['data']};
|
||||
return {
|
||||
'status': true,
|
||||
'data': PlayUrlModel.fromJson(res.data['data'])
|
||||
};
|
||||
} else {
|
||||
return {'status': false, 'data': []};
|
||||
}
|
||||
|
181
lib/models/video/play/url.dart
Normal file
181
lib/models/video/play/url.dart
Normal file
@ -0,0 +1,181 @@
|
||||
class PlayUrlModel {
|
||||
PlayUrlModel({
|
||||
this.from,
|
||||
this.result,
|
||||
this.message,
|
||||
this.quality,
|
||||
this.format,
|
||||
this.timeLength,
|
||||
this.acceptFormat,
|
||||
this.acceptDesc,
|
||||
this.acceptQuality,
|
||||
this.videoCodecid,
|
||||
this.seekParam,
|
||||
this.seekType,
|
||||
this.dash,
|
||||
this.supportFormats,
|
||||
// this.highFormat,
|
||||
this.lastPlayTime,
|
||||
this.lastPlayCid,
|
||||
});
|
||||
|
||||
String? from;
|
||||
String? result;
|
||||
String? message;
|
||||
int? quality;
|
||||
String? format;
|
||||
int? timeLength;
|
||||
String? acceptFormat;
|
||||
List<dynamic>? acceptDesc;
|
||||
List<dynamic>? acceptQuality;
|
||||
int? videoCodecid;
|
||||
String? seekParam;
|
||||
String? seekType;
|
||||
Dash? dash;
|
||||
List? supportFormats;
|
||||
// String? highFormat;
|
||||
int? lastPlayTime;
|
||||
int? lastPlayCid;
|
||||
|
||||
PlayUrlModel.fromJson(Map<String, dynamic> json) {
|
||||
from = json['from'];
|
||||
result = json['result'];
|
||||
message = json['message'];
|
||||
quality = json['quality'];
|
||||
format = json['format'];
|
||||
timeLength = json['timelength'];
|
||||
acceptFormat = json['accept_format'];
|
||||
acceptDesc = json['accept_description'];
|
||||
acceptQuality = json['accept_quality'];
|
||||
videoCodecid = json['video_codecid'];
|
||||
seekParam = json['seek_param'];
|
||||
seekType = json['seek_type'];
|
||||
dash = Dash.fromJson(json['dash']);
|
||||
supportFormats = json['support_formats'];
|
||||
lastPlayTime = json['last_play_time'];
|
||||
lastPlayCid = json['last_play_cid'];
|
||||
}
|
||||
}
|
||||
|
||||
class Dash {
|
||||
Dash({
|
||||
this.duration,
|
||||
this.minBufferTime,
|
||||
this.video,
|
||||
this.audio,
|
||||
this.dolby,
|
||||
this.flac,
|
||||
});
|
||||
|
||||
int? duration;
|
||||
double? minBufferTime;
|
||||
List<VideoItem>? video;
|
||||
List<AudioItem>? audio;
|
||||
Map? dolby;
|
||||
String? flac;
|
||||
|
||||
Dash.fromJson(Map<String, dynamic> json) {
|
||||
duration = json['duration'];
|
||||
minBufferTime = json['minBufferTime'];
|
||||
video = json['video'].map<VideoItem>((e) => VideoItem.fromJson(e)).toList();
|
||||
audio = json['audio'].map<AudioItem>((e) => AudioItem.fromJson(e)).toList();
|
||||
dolby = json['dolby'];
|
||||
flac = json['flac'] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
class VideoItem {
|
||||
VideoItem({
|
||||
this.id,
|
||||
this.baseUrl,
|
||||
this.backupUrl,
|
||||
this.bandWidth,
|
||||
this.mimeType,
|
||||
this.codecs,
|
||||
this.width,
|
||||
this.height,
|
||||
this.frameRate,
|
||||
this.sar,
|
||||
this.startWithSap,
|
||||
this.segmentBase,
|
||||
this.codecid,
|
||||
});
|
||||
|
||||
int? id;
|
||||
String? baseUrl;
|
||||
String? backupUrl;
|
||||
int? bandWidth;
|
||||
String? mimeType;
|
||||
String? codecs;
|
||||
int? width;
|
||||
int? height;
|
||||
String? frameRate;
|
||||
String? sar;
|
||||
int? startWithSap;
|
||||
Map? segmentBase;
|
||||
int? codecid;
|
||||
|
||||
VideoItem.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
baseUrl = json['baseUrl'];
|
||||
backupUrl = json['backupUrl'].toList().first;
|
||||
bandWidth = json['bandWidth'];
|
||||
mimeType = json['mime_type'];
|
||||
codecs = json['codecs'];
|
||||
width = json['width'];
|
||||
height = json['height'];
|
||||
frameRate = json['frameRate'];
|
||||
sar = json['sar'];
|
||||
startWithSap = json['startWithSap'];
|
||||
segmentBase = json['segmentBase'];
|
||||
codecid = json['codecid'];
|
||||
}
|
||||
}
|
||||
|
||||
class AudioItem {
|
||||
AudioItem({
|
||||
this.id,
|
||||
this.baseUrl,
|
||||
this.backupUrl,
|
||||
this.bandWidth,
|
||||
this.mimeType,
|
||||
this.codecs,
|
||||
this.width,
|
||||
this.height,
|
||||
this.frameRate,
|
||||
this.sar,
|
||||
this.startWithSap,
|
||||
this.segmentBase,
|
||||
this.codecid,
|
||||
});
|
||||
|
||||
int? id;
|
||||
String? baseUrl;
|
||||
String? backupUrl;
|
||||
int? bandWidth;
|
||||
String? mimeType;
|
||||
String? codecs;
|
||||
int? width;
|
||||
int? height;
|
||||
String? frameRate;
|
||||
String? sar;
|
||||
int? startWithSap;
|
||||
Map? segmentBase;
|
||||
int? codecid;
|
||||
|
||||
AudioItem.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
baseUrl = json['baseUrl'];
|
||||
backupUrl = json['backupUrl'].toList().first;
|
||||
bandWidth = json['bandWidth'];
|
||||
mimeType = json['mime_type'];
|
||||
codecs = json['codecs'];
|
||||
width = json['width'];
|
||||
height = json['height'];
|
||||
frameRate = json['frameRate'];
|
||||
sar = json['sar'];
|
||||
startWithSap = json['startWithSap'];
|
||||
segmentBase = json['segmentBase'];
|
||||
codecid = json['codecid'];
|
||||
}
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_meedu_media_kit/meedu_player.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/constants.dart';
|
||||
import 'package:pilipala/http/video.dart';
|
||||
import 'package:pilipala/models/video/play/url.dart';
|
||||
import 'package:pilipala/models/video/reply/item.dart';
|
||||
import 'package:pilipala/pages/video/detail/replyReply/index.dart';
|
||||
|
||||
@ -79,11 +81,12 @@ class VideoDetailController extends GetxController {
|
||||
});
|
||||
}
|
||||
|
||||
playerInit(url) {
|
||||
playerInit(source, audioSource, {Duration defaultST = Duration.zero}) {
|
||||
meeduPlayerController.setDataSource(
|
||||
DataSource(
|
||||
type: DataSourceType.network,
|
||||
source: url,
|
||||
source: source,
|
||||
audioSource: audioSource,
|
||||
httpHeaders: {
|
||||
'user-agent':
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15',
|
||||
@ -91,7 +94,8 @@ class VideoDetailController extends GetxController {
|
||||
},
|
||||
),
|
||||
autoplay: true,
|
||||
looping: false
|
||||
looping: false,
|
||||
seekTo: defaultST,
|
||||
);
|
||||
}
|
||||
|
||||
@ -108,7 +112,16 @@ class VideoDetailController extends GetxController {
|
||||
// 视频链接
|
||||
queryVideoUrl() async {
|
||||
var result = await VideoHttp.videoUrl(cid: cid, avid: aid);
|
||||
var url = result['data']['durl'].first['url'];
|
||||
playerInit(url);
|
||||
// log('result: ${result.toString()}');
|
||||
if (result['status']) {
|
||||
PlayUrlModel data = result['data'];
|
||||
print(data.dash);
|
||||
|
||||
// 指定质量的视频 -> 最高质量的视频
|
||||
String videoUrl = data.dash!.video!.first.baseUrl!;
|
||||
String audioUrl = data.dash!.audio!.first.baseUrl!;
|
||||
playerInit(videoUrl, audioUrl,
|
||||
defaultST: Duration(milliseconds: data.lastPlayTime!));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user