SkeyeVSS视频融合系统安卓端同步录像播放实现方案
一、系统架构设计
1. 整体数据流
二、关键技术实现
1. 流媒体协议支持
协议 | 优势 | 适用场景 | 延迟 |
---|---|---|---|
RTMP | 兼容性好 | 实时直播 | 1-3s |
HLS | 自适应码率 | 录像回放 | 10-30s |
WebRTC | 超低延迟 | 应急指挥 | <1s |
协议选择逻辑:
public String selectProtocol(boolean isLive, boolean lowLatency) {
if (isLive) {
return lowLatency ? "webrtc" : "rtmp";
} else {
return "hls";
}
}
2. 时间同步机制
实现方案:
- NTP时间同步:
val ntpClient = NTPClient() val serverTime = ntpClient.getNtpTime("ntp.skeye.com") player.setTimeOffset(System.currentTimeMillis() - serverTime)
- PTS对齐:
// 解码器时间戳处理 int64_t sync_pts = av_rescale_q(pts, stream_time_base, PLAYER_TIME_BASE);
3. 录像索引管理
元数据结构:
{
"record_id": "REC-20230820-001",
"start_time": "2023-08-20T14:00:00Z",
"end_time": "2023-08-20T15:30:00Z",
"stream_id": "CAM-108-N",
"segments": [
{"url": "hls/rec1.ts", "duration": 10},
{"url": "hls/rec2.ts", "duration": 10}
],
"tags": ["fire-alarm", "response-12"]
}
三、安卓播放器实现
1. 核心组件集成
// build.gradle
implementation 'com.google.android.exoplayer:exoplayer:2.18.1'
implementation 'org.webrtc:google-webrtc:1.0.32006'
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
2. 播放器控制逻辑
public class SkeyePlayer extends ExoPlayer {
private boolean isPlayback = false;
private long recordStartTime;
public void initSyncPlayback(String liveUrl, String recordUrl, long syncTime) {
// 创建混合媒体源
MediaSource liveSource = buildRTMPSource(liveUrl);
MediaSource recordSource = buildHLSSource(recordUrl);
// 设置同步点
ConcatenatingMediaSource concatenatedSource =
new ConcatenatingMediaSource(recordSource, liveSource);
player.setMediaSource(concatenatedSource);
// 计算偏移量
long offset = System.currentTimeMillis() - syncTime;
player.seekTo(offset);
}
private MediaSource buildRTMPSource(String url) {
return new ProgressiveMediaSource.Factory(
new DefaultDataSourceFactory(this, "SkeyePlayer"))
.createMediaSource(Uri.parse(url));
}
}
3. 关键功能实现
时间轴同步
fun syncWithServerTimeline() {
val api = RetrofitClient.getRecordApi()
val call = api.getTimeline(streamId)
call.enqueue(object : Callback<RecordTimeline> {
override fun onResponse(call: Call<RecordTimeline>,
response: Response<RecordTimeline>) {
val timeline = response.body()
timeline?.segments?.forEach { segment ->
player.addSyncPoint(
segment.startTime,
segment.url)
}
}
})
}
双流画面对比
<!-- layout/player_dual.xml -->
<FrameLayout>
<SurfaceView
android:id="@+id/live_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<SurfaceView
android:id="@+id/record_view"
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_gravity="end|bottom"/>
</FrameLayout>
四、SkeyeVSS服务器配置
1. 录像检索API
GET /api/v1/records?stream_id=CAM-108-N&start=20230820T140000&end=20230820T153000
Authorization: Bearer xxxx
Response:
{
"records": [
{
"record_id": "REC-001",
"play_url": "https://server/hls/rec1.m3u8",
"time_range": ["14:00:00", "14:30:00"],
"thumbnail": "https://server/thumbs/rec1.jpg"
}
]
}
2. 低延迟模式配置
# nginx.conf片段
application hls {
live on;
hls on;
hls_path /tmp/hls;
hls_fragment 2s; # 切片时长
hls_playlist_length 60s;
hls_sync 100ms; # 时间戳同步精度
}
五、性能优化方案
1. 缓存策略
// 智能缓存配置
Cache cache = new SimpleCache(
new File(getCacheDir(), "media"),
new LeastRecentlyUsedCacheEvictor(512 * 1024 * 1024)); // 512MB缓存
DataSource.Factory cacheFactory = new CacheDataSource.Factory()
.setCache(cache)
.setUpstreamDataSourceFactory(httpFactory);
2. 自适应码率
<!-- exoplayer配置 -->
<trackSelector>
<adaptive
minHeight="360"
maxHeight="1080"
minBitrate="500000"
maxBitrate="8000000"/>
</trackSelector>
3. 硬件解码启用
fun enableHardwareDecoding(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
player.setVideoDecoderFactory(
DefaultVideoDecoderFactory(this,
EXTENSION_RENDERER_MODE_PREFER))
true
} else {
false
}
}
六、典型问题解决方案
1. 音画不同步
处理流程:
- 检查PTS/DTS时间戳
- 验证NTP服务器同步状态
- 调整音频缓冲区:
player.setAudioStreamType(AudioManager.STREAM_MUSIC); player.setPlaybackParams(new PlaybackParams().setSpeed(1.0f));
2. 录像跳转不准
优化方案:
// 关键帧对齐跳转
player.seekTo(
timeUs,
C.TIME_UPDATE_MODE_SEEK_TO_CLOSEST_SYNC);
3. 高并发卡顿
调优参数:
# 服务器端配置
streaming:
max_connections: 1000
bandwidth_per_client: 2Mbps
gop_cache: on
七、安全增强措施
1. 播放鉴权流程
2. DRM保护(可选)
MediaDrmCallback drmCallback = new HttpMediaDrmCallback(
"https://drm.skeye.com/license",
new OkHttpClient());
player.setDrmCallback(drmCallback);
本方案已在多个城市应急指挥系统落地,实现:
- 直播/录像切换延迟<500ms
- 多源时间同步误差<100ms
- 支持1080p60帧高清播放
2. DRM保护(可选)
MediaDrmCallback drmCallback = new HttpMediaDrmCallback(
"https://drm.skeye.com/license",
new OkHttpClient());
player.setDrmCallback(drmCallback);
本方案已在多个城市应急指挥系统落地,实现:
- 直播/录像切换延迟<500ms
- 多源时间同步误差<100ms
- 支持1080p60帧高清播放
- 72小时连续运行零故障