parent
85b2729a04
commit
378c4cbdf8
|
@ -1,80 +0,0 @@
|
||||||
package com.guwan.backend.controller;
|
|
||||||
|
|
||||||
import com.guwan.backend.common.Result;
|
|
||||||
import com.guwan.backend.dto.live.CreateRoomRequest;
|
|
||||||
import com.guwan.backend.dto.live.StartLiveRequest;
|
|
||||||
import com.guwan.backend.dto.live.WebRTCRequest;
|
|
||||||
import com.guwan.backend.dto.live.WebRTCResponse;
|
|
||||||
import com.guwan.backend.entity.LiveRoom;
|
|
||||||
import com.guwan.backend.service.LiveStreamService;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Tag(name = "直播管理", description = "直播相关接口")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/live")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class LiveStreamController {
|
|
||||||
|
|
||||||
private final LiveStreamService liveStreamService;
|
|
||||||
|
|
||||||
@Operation(summary = "创建直播间")
|
|
||||||
@PostMapping("/room")
|
|
||||||
public Result<LiveRoom> createLiveRoom(@RequestBody CreateRoomRequest request) {
|
|
||||||
try {
|
|
||||||
LiveRoom room = liveStreamService.createLiveRoom(
|
|
||||||
request.getTitle(),
|
|
||||||
request.getDescription(),
|
|
||||||
request.getUserId()
|
|
||||||
);
|
|
||||||
return Result.success(room);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("创建直播间失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "开始直播")
|
|
||||||
@PostMapping("/room/{id}/start")
|
|
||||||
public Result<Void> startLive(
|
|
||||||
@PathVariable Long id,
|
|
||||||
@RequestBody StartLiveRequest request) {
|
|
||||||
try {
|
|
||||||
liveStreamService.startLive(id, request.getSourceUrl());
|
|
||||||
return Result.success();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("开始直播失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "结束直播")
|
|
||||||
@PostMapping("/room/{id}/end")
|
|
||||||
public Result<Void> endLive(@PathVariable Long id) {
|
|
||||||
try {
|
|
||||||
liveStreamService.endLive(id);
|
|
||||||
return Result.success();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("结束直播失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "获取WebRTC Offer")
|
|
||||||
@PostMapping("/room/{id}/webrtc")
|
|
||||||
public Result<WebRTCResponse> getWebRTCOffer(
|
|
||||||
@PathVariable Long id,
|
|
||||||
@RequestBody WebRTCRequest request) {
|
|
||||||
try {
|
|
||||||
String sdp = liveStreamService.getWebRTCOffer(id, request.getSdp());
|
|
||||||
return Result.success(new WebRTCResponse(sdp));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取WebRTC Offer失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,130 +0,0 @@
|
||||||
package com.guwan.backend.controller;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.guwan.backend.common.Result;
|
|
||||||
import com.guwan.backend.dto.video.VideoDTO;
|
|
||||||
import com.guwan.backend.dto.video.VideoUploadDTO;
|
|
||||||
import com.guwan.backend.service.VideoService;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Tag(name = "视频管理", description = "视频相关接口")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/videos")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class VideoController {
|
|
||||||
|
|
||||||
private final VideoService videoService;
|
|
||||||
|
|
||||||
|
|
||||||
@Operation(summary = "上传视频", description = "上传视频文件并返回视频信息")
|
|
||||||
// @SecurityRequirement(name = "bearer-jwt")
|
|
||||||
@PostMapping("/upload")
|
|
||||||
public Result<VideoDTO> uploadVideo(@RequestBody VideoUploadDTO videoUploadDTO) {
|
|
||||||
try {
|
|
||||||
VideoDTO video = videoService.uploadVideo(videoUploadDTO.getFileUrl(),
|
|
||||||
videoUploadDTO.getTitle(), videoUploadDTO.getDescription(), videoUploadDTO.getTags());
|
|
||||||
return Result.success(video);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("上传视频失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "更新视频信息")
|
|
||||||
@SecurityRequirement(name = "bearer-jwt")
|
|
||||||
@PutMapping("/{id}")
|
|
||||||
public Result<VideoDTO> updateVideo(
|
|
||||||
@Parameter(description = "视频ID") @PathVariable Long id,
|
|
||||||
@RequestBody VideoDTO videoDTO) {
|
|
||||||
try {
|
|
||||||
videoDTO.setId(id);
|
|
||||||
return Result.success(videoService.updateVideo(videoDTO));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("更新视频失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "删除视频")
|
|
||||||
@SecurityRequirement(name = "bearer-jwt")
|
|
||||||
@DeleteMapping("/{id}")
|
|
||||||
public Result<Void> deleteVideo(
|
|
||||||
@Parameter(description = "视频ID") @PathVariable Long id) {
|
|
||||||
try {
|
|
||||||
videoService.deleteVideo(id);
|
|
||||||
return Result.success();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("删除视频失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "获取视频详情")
|
|
||||||
@GetMapping("/{id}")
|
|
||||||
public Result<VideoDTO> getVideo(
|
|
||||||
@Parameter(description = "视频ID") @PathVariable Long id) {
|
|
||||||
try {
|
|
||||||
VideoDTO video = videoService.getVideoById(id);
|
|
||||||
if (video == null) {
|
|
||||||
return Result.notFound("视频不存在");
|
|
||||||
}
|
|
||||||
return Result.success(video);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取视频失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "获取视频列表", description = "支持分页和关键词搜索")
|
|
||||||
@GetMapping
|
|
||||||
public Result<IPage<VideoDTO>> getVideoList(
|
|
||||||
@Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
|
|
||||||
@Parameter(description = "每页条数") @RequestParam(defaultValue = "10") Integer pageSize,
|
|
||||||
@Parameter(description = "搜索关键词") @RequestParam(required = false) String keyword) {
|
|
||||||
try {
|
|
||||||
return Result.success(videoService.getVideoList(pageNum, pageSize, keyword));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取视频列表失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "增加视频观看次数")
|
|
||||||
@PostMapping("/{id}/view")
|
|
||||||
public Result<Void> incrementViewCount(
|
|
||||||
@Parameter(description = "视频ID") @PathVariable Long id) {
|
|
||||||
try {
|
|
||||||
videoService.incrementViewCount(id);
|
|
||||||
return Result.success();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("增加观看次数失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "视频点赞/取消点赞")
|
|
||||||
@SecurityRequirement(name = "bearer-jwt")
|
|
||||||
@PostMapping("/{id}/like")
|
|
||||||
public Result<Void> toggleLike(
|
|
||||||
@Parameter(description = "视频ID") @PathVariable Long id) {
|
|
||||||
try {
|
|
||||||
videoService.toggleLike(id);
|
|
||||||
return Result.success();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("点赞失败", e);
|
|
||||||
return Result.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
//package com.guwan.backend.service;
|
|
||||||
//
|
|
||||||
//import com.guwan.backend.client.SrsClient;
|
|
||||||
//import com.guwan.backend.dto.live.LiveRoomDTO;
|
|
||||||
//import com.guwan.backend.entity.LiveRoom;
|
|
||||||
//import com.guwan.backend.mapper.LiveRoomMapper;
|
|
||||||
//import com.guwan.backend.util.SecurityUtil;
|
|
||||||
//import lombok.RequiredArgsConstructor;
|
|
||||||
//import lombok.extern.slf4j.Slf4j;
|
|
||||||
//import org.springframework.beans.BeanUtils;
|
|
||||||
//import org.springframework.stereotype.Service;
|
|
||||||
//
|
|
||||||
//@Slf4j
|
|
||||||
//@Service
|
|
||||||
//@RequiredArgsConstructor
|
|
||||||
//public class LiveService {
|
|
||||||
//
|
|
||||||
// private final LiveRoomMapper liveRoomMapper;
|
|
||||||
// private final SrsClient srsClient;
|
|
||||||
// private final SecurityUtil securityUtil;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 创建直播间
|
|
||||||
// */
|
|
||||||
// public LiveRoom createLiveRoom(LiveRoomDTO dto) {
|
|
||||||
// // 获取当前用户
|
|
||||||
// Long userId = securityUtil.getCurrentUserId();
|
|
||||||
// String username = securityUtil.getCurrentUsername();
|
|
||||||
// if (userId == null) {
|
|
||||||
// throw new IllegalStateException("用户未登录");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// LiveRoom room = new LiveRoom();
|
|
||||||
// BeanUtils.copyProperties(dto, room);
|
|
||||||
//
|
|
||||||
// // 设置用户信息
|
|
||||||
// room.setUserId(userId);
|
|
||||||
// room.setUsername(username);
|
|
||||||
//
|
|
||||||
// // 生成推流密钥
|
|
||||||
// String streamKey = generateStreamKey();
|
|
||||||
// room.setStreamKey(streamKey);
|
|
||||||
//
|
|
||||||
// // 生成推流地址
|
|
||||||
// String rtmpUrl = generateRtmpUrl(streamKey);
|
|
||||||
// room.setRtmpUrl(rtmpUrl);
|
|
||||||
//
|
|
||||||
// // 生成播放地址
|
|
||||||
// String hlsUrl = generateHlsUrl(streamKey);
|
|
||||||
// room.setHlsUrl(hlsUrl);
|
|
||||||
//
|
|
||||||
// room.setStatus("PREPARING");
|
|
||||||
// room.setOnlineCount(0);
|
|
||||||
// room.setLikeCount(0);
|
|
||||||
//
|
|
||||||
// liveRoomMapper.insert(room);
|
|
||||||
// return room;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 开始直播
|
|
||||||
// */
|
|
||||||
// public void startLive(Long roomId) {
|
|
||||||
// LiveRoom room = liveRoomMapper.selectById(roomId);
|
|
||||||
// room.setStatus("LIVING");
|
|
||||||
// liveRoomMapper.updateById(room);
|
|
||||||
//
|
|
||||||
// // 开始录制
|
|
||||||
// startRecording(room.getStreamKey());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 结束直播
|
|
||||||
// */
|
|
||||||
// public void endLive(Long roomId) {
|
|
||||||
// LiveRoom room = liveRoomMapper.selectById(roomId);
|
|
||||||
// room.setStatus("ENDED");
|
|
||||||
// liveRoomMapper.updateById(room);
|
|
||||||
//
|
|
||||||
// // 停止录制
|
|
||||||
// stopRecording(room.getStreamKey());
|
|
||||||
//
|
|
||||||
// // 生成回放地址
|
|
||||||
// String replayUrl = generateReplayUrl(room.getStreamKey());
|
|
||||||
// room.setReplayUrl(replayUrl);
|
|
||||||
// liveRoomMapper.updateById(room);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 开始录制
|
|
||||||
// */
|
|
||||||
// private void startRecording(String streamKey) {
|
|
||||||
// SrsClient.RecordConfig config = new SrsClient.RecordConfig();
|
|
||||||
// config.setFilePath("/recordings/" + streamKey + ".flv");
|
|
||||||
// srsClient.startRecord(streamKey, config);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 停止录制
|
|
||||||
// */
|
|
||||||
// private void stopRecording(String streamKey) {
|
|
||||||
// srsClient.stopRecord(streamKey);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 生成推流密钥
|
|
||||||
// */
|
|
||||||
// private String generateStreamKey() {
|
|
||||||
// return UUID.randomUUID().toString();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 生成推流地址
|
|
||||||
// */
|
|
||||||
// private String generateRtmpUrl(String streamKey) {
|
|
||||||
// return "rtmp://localhost:1935/live/" + streamKey;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 生成播放地址
|
|
||||||
// */
|
|
||||||
// private String generateHlsUrl(String streamKey) {
|
|
||||||
// return "http://localhost:8088/live/" + streamKey + ".m3u8";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 生成回放地址
|
|
||||||
// */
|
|
||||||
// private String generateReplayUrl(String streamKey) {
|
|
||||||
// return "http://localhost:8080/recordings/" + streamKey + ".flv";
|
|
||||||
// }
|
|
||||||
//}
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.guwan.backend.service;
|
package com.guwan.backend.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.guwan.backend.dto.ReadingStatistics;
|
||||||
import com.guwan.backend.entity.ReadingProgress;
|
import com.guwan.backend.entity.ReadingProgress;
|
||||||
|
|
||||||
public interface ReadingProgressService {
|
public interface ReadingProgressService {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.guwan.backend.service.impl;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.guwan.backend.dto.ReadingStatistics;
|
||||||
import com.guwan.backend.entity.ReadingProgress;
|
import com.guwan.backend.entity.ReadingProgress;
|
||||||
import com.guwan.backend.mapper.ReadingProgressMapper;
|
import com.guwan.backend.mapper.ReadingProgressMapper;
|
||||||
import com.guwan.backend.service.ReadingProgressService;
|
import com.guwan.backend.service.ReadingProgressService;
|
||||||
|
|
Loading…
Reference in New Issue