| | |
| | | import com.doumee.dao.business.model.CollectionMedia; |
| | | import com.doumee.dao.business.model.CollectionStation; |
| | | import com.doumee.service.business.CollectionMediaSyncService; |
| | | import com.doumee.service.business.DeliverySnapshotService; |
| | | import com.doumee.service.business.collection.CollectionMediaConstants; |
| | | import com.doumee.service.business.third.model.PageData; |
| | | import com.doumee.service.business.third.model.PageWrap; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Qualifier; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | |
| | | private CollectionMediaMapper collectionMediaMapper; |
| | | @Autowired |
| | | private CollectionStationMapper collectionStationMapper; |
| | | @Autowired |
| | | private DeliverySnapshotService deliverySnapshotService; |
| | | @Autowired |
| | | private SystemDictDataBiz systemDictDataBiz; |
| | | @Resource(name = "asyncExecutor") |
| | |
| | | if (station == null || Constants.equalsInteger(station.getIsdeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | List<MediaItemDTO> items = isapiClient.searchMediaAll(station, startTime, endTime, trackId, IsapiConstants.MAX_PAGE_RESULTS); |
| | | List<MediaItemDTO> items = isapiClient.searchMediaAll(station, startTime, endTime, |
| | | resolveSyncTrackId(trackId), IsapiConstants.MAX_PAGE_RESULTS); |
| | | log.info("采集站媒体检索 stationId={} ip={} range={}~{} track={} found={}", |
| | | stationId, station.getIp(), startTime, endTime, trackId, items.size()); |
| | | stationId, station.getIp(), startTime, endTime, resolveSyncTrackId(trackId), items.size()); |
| | | int count = 0; |
| | | int skipped = 0; |
| | | Date now = new Date(); |
| | | for (MediaItemDTO item : items) { |
| | | if (StringUtils.isBlank(item.getFileIndex())) { |
| | | continue; |
| | | } |
| | | if (!isSyncableMp4Video(item)) { |
| | | skipped++; |
| | | continue; |
| | | } |
| | | Long exists = collectionMediaMapper.selectCount(new QueryWrapper<CollectionMedia>().lambda() |
| | |
| | | collectionMediaMapper.insert(media); |
| | | count++; |
| | | } |
| | | if (skipped > 0) { |
| | | log.info("采集站媒体索引跳过非MP4视频 stationId={} skipped={}", stationId, skipped); |
| | | } |
| | | return count; |
| | | } |
| | | |
| | | /** 同步索引仅检索主码流录像 track(默认 101),不包含抓图 track 103 */ |
| | | private String resolveSyncTrackId(String trackId) { |
| | | if (StringUtils.isNotBlank(trackId)) { |
| | | String val = trackId.trim(); |
| | | if (!"auto".equalsIgnoreCase(val) && !"*".equals(val) && !"0".equals(val)) { |
| | | return val; |
| | | } |
| | | } |
| | | return IsapiConstants.DEFAULT_TRACK_ID; |
| | | } |
| | | |
| | | /** 同步入库:仅 MP4 视频(扩展名 .mp4,且非图片/音频类型) */ |
| | | private static boolean isSyncableMp4Video(MediaItemDTO item) { |
| | | if (item.getMediaType() != null && item.getMediaType() != 0) { |
| | | return false; |
| | | } |
| | | String trackId = StringUtils.defaultString(item.getTrackId()); |
| | | if (trackId.endsWith("3")) { |
| | | return false; |
| | | } |
| | | return isMp4FileName(resolveItemFileName(item)); |
| | | } |
| | | |
| | | private static String resolveItemFileName(MediaItemDTO item) { |
| | | if (StringUtils.isNotBlank(item.getFileName())) { |
| | | return item.getFileName(); |
| | | } |
| | | String uri = item.getPlaybackUri(); |
| | | if (StringUtils.isBlank(uri)) { |
| | | return null; |
| | | } |
| | | java.util.regex.Matcher m = java.util.regex.Pattern |
| | | .compile("[?&](?:name|filename|fileName)=([^&\\s]+)", java.util.regex.Pattern.CASE_INSENSITIVE) |
| | | .matcher(uri.replace("&", "&")); |
| | | if (m.find()) { |
| | | try { |
| | | return java.net.URLDecoder.decode(m.group(1), StandardCharsets.UTF_8.name()); |
| | | } catch (Exception e) { |
| | | return m.group(1); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (Constants.equalsInteger(media.getDownloadStatus(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "文件已下载,无需重复下载"); |
| | | } |
| | | if (Constants.equalsInteger(media.getDownloadStatus(), Constants.COLLECTION_MEDIA_DOWNLOADING)) { |
| | | if (Constants.equalsInteger(media.getDownloadStatus(), CollectionMediaConstants.DOWNLOAD_STATUS_DOWNLOADING)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "文件正在下载中,请稍后刷新"); |
| | | } |
| | | CollectionStation station = collectionStationMapper.selectById(media.getStationId()); |
| | |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | CollectionMedia downloading = new CollectionMedia(); |
| | | downloading.setDownloadStatus(Constants.COLLECTION_MEDIA_DOWNLOADING); |
| | | downloading.setDownloadStatus(CollectionMediaConstants.DOWNLOAD_STATUS_DOWNLOADING); |
| | | int updated = collectionMediaMapper.update(downloading, new QueryWrapper<CollectionMedia>().lambda() |
| | | .eq(CollectionMedia::getId, mediaId) |
| | | .in(CollectionMedia::getDownloadStatus, Constants.ZERO, 2)); |
| | |
| | | update.setDownloadTime(new Date()); |
| | | collectionMediaMapper.updateById(update); |
| | | log.info("异步下载成功 mediaId={} path={}", mediaId, path); |
| | | deliverySnapshotService.submitAnalyzeAsync(mediaId); |
| | | } catch (Exception e) { |
| | | markDownloadFailed(mediaId); |
| | | log.error("异步下载异常 mediaId={}: {}", mediaId, e.getMessage(), e); |