爱优腾广告太多,于是我自己搭了一个视频播放网站

爱优腾广告太多,于是我自己搭了一个视频播放网站

最终效果

PC端

image.png

手机端

image.png

视频详情

image.png

视频播放 image.png

视频播放网站简介

视频播放网站是互联网上的重要平台,为用户提供各种类型的视频内容,包括电影、电视剧、综艺节目、纪录片、动漫等。这些网站通常拥有海量的视频资源,并且提供高清流畅的播放体验,让用户能够随时随地享受视频娱乐的乐趣。

在中国,有许多知名的视频播放网站,如优酷、爱奇艺、腾讯视频、搜狐视频等。这些网站不仅拥有大量的正版视频资源,还积极推广优质内容,提高用户的观影体验。此外,它们还通过提供个性化推荐、互动评论等功能,增加用户的参与度和粘性。

视频播放网站的成功得益于互联网技术的不断发展和用户需求的不断变化。随着移动互联网的普及和5G技术的应用,用户对于视频内容的需求越来越高,对于播放体验的要求也越来越高。因此,视频播放网站需要不断创新和改进,以满足用户的需求,保持竞争优势。

然而,视频播放网站也面临着一些挑战和问题。例如,版权保护、内容审核、广告投放等方面的问题都需要得到有效的解决。此外,随着市场竞争的加剧,网站之间需要不断提升自己的内容质量和服务水平,才能赢得用户的信任和支持。

总的来说,视频播放网站在为用户提供便捷、高效的视频娱乐服务的同时,也需要不断适应市场变化和技术发展,以保持领先地位并实现可持续发展。

网站技术

springboot+thymeleaf+mysql

码云地址

腾讯免费领取一个月虚拟主机

image.png

image.png

表结构

CREATE TABLE `video_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `video_name` varchar(255) NOT NULL COMMENT '视频名称',
  `video_classification` int(2) NOT NULL COMMENT '视频分类',
  `video_image` varchar(255) NOT NULL COMMENT '视频图片',
  `video_description` varchar(255) NOT NULL COMMENT '视频描述',
  `update_info` varchar(255) NOT NULL COMMENT '更新信息',
  `area` varchar(255) NOT NULL COMMENT '地区',
  `story_line` varchar(255) NOT NULL COMMENT '情节',
  `which_episode` int(11) NOT NULL COMMENT '更新到第几集',
  `video_type` varchar(255) NOT NULL COMMENT '类型',
  `years` varchar(50) NOT NULL COMMENT '年代',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='视频信息表';

CREATE TABLE `video_view` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `video_info_id` int(11) NOT NULL COMMENT '视频信息ID',
  `video_view_index` varchar(255) NOT NULL COMMENT '视频播放顺序(第几集)',
  `video_url` varchar(255) NOT NULL COMMENT '视频地址',
  `upload_time` datetime NOT NULL COMMENT '上传时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='视频播放表';

Maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tangshuai.video</groupId>
    <artifactId>HomeTheater</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- SpringBoot核心jar包 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>HomeTheater</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

配置文件

server.port=80
#设置 thymeleaf 页面缓存失效
spring.thymeleaf.cache=false
#thymeleaf 模版前缀,默认值,可选项
spring.thymeleaf.prefix=classpath:/templates/
#thymeleaf 模版后缀,默认值,可选项
spring.thymeleaf.suffix=.html
#数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 解决返回页面中文乱码问题
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8

代码片段

package com.tangshuai.video.controller;

import com.tangshuai.video.constant.SystemConstant;
import com.tangshuai.video.po.VideoInfo;
import com.tangshuai.video.po.VideoView;
import com.tangshuai.video.service.VideoInfoService;
import com.tangshuai.video.service.VideoViewService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Date;
import java.util.List;

/**
 * @Author TANGSHUAI
 * @Date 2024-03-03 21:40
 **/
@Controller
@RequestMapping("/video")
public class VideoInfoController {

    private Logger logger = LoggerFactory.getLogger(IndexController.class);

    @Autowired
    private VideoInfoService videoInfoService;

    @Autowired
    private VideoViewService videoViewService;

    /**
     * 分页查询视频信息
     * @param request
     * @param videoInfo
     * @return
     */
    /*@RequestMapping("/selectAllVideoInfo")
    public String selectAllVideoInfo(HttpServletRequest request, VideoInfo videoInfo) {
        System.out.println(videoInfo);
        String ipAddress = request.getRemoteAddr();
        logger.info("访问客户端IP地址: {}" ,ipAddress);
        IPage<VideoInfo> videoInfoIPage = videoInfoService.selectAllVideoInfo(1, 20);
        request.setAttribute("videoInfoIPage", videoInfoIPage);
        return "index";
    }*/

    /**
     * 视频详情
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/detail")
    public String detail(HttpServletRequest request,Integer id){
        VideoInfo videoInfo = videoInfoService.selectByIdVideoInfo(id);
        VideoView videoView=new VideoView();
        videoView.setVideoInfoId(videoInfo.getId());
        List<VideoView> videoViews = videoViewService.selectByVideoInfoId(videoView);
        String ipAddress = request.getRemoteAddr();
        logger.info("访问客户端IP地址: {}" ,ipAddress);
        logger.info("视频详情: {}" ,videoInfo);
        request.setAttribute("videoInfo",videoInfo);
        request.setAttribute("videoViews",videoViews);
        return "detail";
    }

    /**
     * 播放视频
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/videoPlay")
    public String video(HttpServletRequest request,Integer id){
        VideoView videoView = videoViewService.selectById(id);
        String ipAddress = request.getRemoteAddr();
        logger.info("访问客户端IP地址: {}" ,ipAddress);
        logger.info("播放视频: {}" ,videoView);
        VideoView view=new VideoView();
        view.setVideoInfoId(videoView.getVideoInfoId());
        List<VideoView> videoViewList = videoViewService.selectByVideoInfoId(view);
        request.setAttribute("videoViewList",videoViewList);
        request.setAttribute("videoView",videoView);
        return "video";
    }

    /**
     * 同步视频
     * @param directory
     * @return
     */
    @RequestMapping("/videoSync/{directory}")
    @ResponseBody
    @Transactional
    public String videoSync(@PathVariable("directory") String directory){
        if(null==directory){
            logger.error("请输入正确的目录:{}",directory);
            throw new NullPointerException("请输入正确的目录!");
        }
        logger.info("要同步的目录:{}",directory);
        // 查询数据库中是否存在该目录
        VideoInfo vf=videoInfoService.selectByVideoName(directory);
        if(null!=vf){
            logger.error("视频已存在,同步失败!{}",directory);
            throw new NullPointerException("视频已存在,同步失败!");
        }
        File fileDirectory=new File(SystemConstant.FILEPARTITION+directory);
        File[] files = fileDirectory.listFiles();
        VideoInfo videoInfo=new VideoInfo();
        videoInfo.setVideoName(directory);
        videoInfo.setArea("中国");
        videoInfo.setCreate_time(new Date());
        videoInfo.setStoryLine(directory);
        videoInfo.setVideoType(directory);
        videoInfo.setVideoClassification(1);
        videoInfo.setVideoImage("/tv/"+"load.gif");
        videoInfo.setVideoDescription(directory);
        videoInfo.setYears("2024");
        videoInfo.setUpdateInfo("最近更新");
        videoInfo.setWhichEpisode(0);
        videoInfoService.addVideoInfo(videoInfo);
        int index=1;
        String videoImage="";
        for (File file : files) {
            if(file.isFile()){
                // 不是图片则插入数据库
                if(!"jpg".equals(file.getName().substring(file.getName().lastIndexOf(".")+1))){
                    VideoView videoView=new VideoView();
                    videoView.setVideoInfoId(videoInfo.getId());
                    videoView.setVideoViewIndex("第"+index+"集");
                    videoView.setUploadTime(new Date());
                    videoView.setVideoUrl("/tv/"+directory+"/"+file.getName());
                    videoViewService.addVideoView(videoView);
                    index+=1;
                }else{
                    videoImage=file.getName();
                }
            }
        }
        logger.info("视频同步成功!{}",directory);
        if(!StringUtils.isEmpty(videoImage)){
            logger.info("视频封面URL:{}",videoImage);
            videoInfo.setVideoImage("/tv/"+directory+"/"+videoImage);
        }
        videoInfo.setWhichEpisode(index);
        videoInfoService.updateVideoInfo(videoInfo);
        return "同步成功";
    }

}