‘SVideo’视频上传

作者: 白晓明 | 来源:发表于2019-04-22 15:58 被阅读6次

对于视频上传与图片上传没有多大区别,主要在我们对视频的处理,如截取某一帧作为封面图,获取视频时长等。

//视频上传
        //对登录用户上传视频进行处理
        if(_file.isEmpty()) {
            return APIResultJson.getFailInstance("视频不能为空!");
        } else {
            //获取当前上传文件的文件名称
            String originalFileName = _file.getOriginalFilename();
            //获取文件后缀名
            String fileSuffix = getExtName(originalFileName, '.');
            //文件新名称
            String newFileName = getUUIDFileName(originalFileName);
            //获取文件上传hash算法路径
            String fileSaveAllPath = makePath(newFileName);
            //绝对路径
            String absolutePath = fileSaveRootPath + fileSaveAllPath;
            //封装上传文件位置的全路径
            File uploadPath = new File(absolutePath, newFileName);
            //把本地文件上传到封装上传文件位置的全路径
            try {
                _file.transferTo(uploadPath);
            } catch (IOException e) {
                APIResultJson.getFailInstance("视频发布失败,请稍后尝试!");
                e.printStackTrace();
            }
            //获取用户上传视频路径,fileSaveAllPath + "\" + newFileName

            //获取视频秒数
            Long videoTimes = VideoUtils.getVideoTime(uploadPath);
            //截取视频中某一针,将其保存为视频封面图
            BufferedImage bi =  VideoUtils.interceptPictureByVideo(uploadPath);

            //重绘图片时先将案例图保存到视频目录下
            String picName = newFileName.substring(0, newFileName.lastIndexOf('.')) + ".jpg";
            String interceptPicturePath = absolutePath + "\\" + picName;
            try {
                ImageIO.write(bi, "jpg", new File(interceptPicturePath));
            } catch (IOException e) {
                APIResultJson.getFailInstance("视频截取图片失败,请重写上传!");
            }
            //保存视频信息到数据库
            VInfo vi = new VInfo();
            vi.setsName(_name);//视频名称
            vi.setsPath(fileSaveAllPath + "\\" + newFileName);//视频存储路径
            vi.setnSeconds(videoTimes);//视频秒数
            vi.setcDesc(_desc);//视频描述
            vi.setsCoverPath(fileSaveAllPath + "\\" + picName);//视频封面图存储路径
            vi.settPubdate(new Date());//发布时间
            vi.setiWcs(Long.valueOf(_wcs));//谁可见
            vi.setcComment(_comment);//是否允许评论
            vi.setcStatus("1");//视频状态
            vi.setiUid(cui.getId());
            vi.settEdit(new Date());

            int result = vis.insertSelective(vi);
            if(result <= 0) {
                return  APIResultJson.getFailInstance("视频发布失败!");
            }
        }

对视频处理我们使用到了JavaCV

1. pom.xml引入Jar
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacpp</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>opencv-platform</artifactId>
            <version>3.4.1-1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>3.4.2-1.4.1</version>
        </dependency>
2.获取指定帧截取为图片
    /**
     * 获取指定视频的帧截取为图片
     * @param file  源视频文件
     * @return
     */
    public static BufferedImage interceptPictureByVideo(File file) {
        //FFmpegFrameGrabber可以理解为解码器,也可以理解为帧收集器
        FFmpegFrameGrabber ffg = new FFmpegFrameGrabber(file);
        try {
            //启动
            ffg.start();
            //获取视频帧长度
            int videoLength = ffg.getLengthInFrames();

            int i = 0;
            Frame frame = null;
            while (i < videoLength) {
                //过滤前5帧,避免出现全黑的图片
                frame = ffg.grabFrame();
                if((i > 5) && (frame.image != null)) {
                    break;
                }
                i++;
            }

            Java2DFrameConverter converter = new Java2DFrameConverter();
            BufferedImage srcBi = converter.getBufferedImage(frame);
            int owidth = srcBi.getWidth();
            int oheight = srcBi.getHeight();
            //对截取的帧进行等比例缩放
            int width = 800;
            int height = (int) ((double)(width / owidth) * oheight);

            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
            ffg.stop();
            return bi;
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
            return null;
        }
    }
3. 获取视频时长
    /**
     * 获取视频时长,单位为秒
     * @param file
     * @return
     */
    public static Long getVideoTime(File file) {
        Long times = 0L;
        FFmpegFrameGrabber ffg = new FFmpegFrameGrabber(file);
        try {
            ffg.start();
            times = ffg.getLengthInTime() / (1000 * 1000);
            ffg.stop();
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
            return times;
        }
        return times;
    }

对文件名进行处理,使用hash算法打散存储防止目录下出现太多文件

    /**
     * 上传文件到服务器时,为防止一个目录下出现太多文件,使用hash算法打散存储
     * @param fileName  文件名称
     * @return
     */
    public String makePath(String fileName) {
        //得到文件名的hashCode的值,得到的就是fileName这个字符串对象在内存中的地址
        int hashCode = fileName.hashCode();
        int dirOPath = hashCode & 0xf;//0--15
        int dirTPath = (hashCode & 0xf0) >> 4;//0-15
        String path = dirOPath + "\\" + dirTPath;
        //构造新的保存目录
        String newPath = fileSaveRootPath + path;
        //File即可代表文件也可以代表目录
        File file = new File(newPath);
        //如果目录不存在,则创建
        if(!file.exists()) {
            file.mkdirs();
        }
        return path;
    }

使用UUID对文件名做处理,防止重复

    /**
     * 将文件名转换成uuid表示,防止文件名上传重复
     * @param fileName
     * @return
     */
    private String getUUIDFileName(String fileName) {
        UUID uuid = UUID.randomUUID();
        StringBuilder sb = new StringBuilder(100);
        sb.append(uuid.toString()).append(".").append(this.getExtName(fileName, '.'));
        return sb.toString();
    }

获取文件后缀

    /**
     * 获取文件后缀名
     * @param s
     * @param split
     * @return
     */
    private String getExtName(String s, char split) {
        int i = s.lastIndexOf(split);
        int leg = s.length();
        return i > 0 ? (i + 1) == leg ? " " : s.substring(i + 1, s.length()) : " ";
    }

相关文章

  • ‘SVideo’视频上传

    对于视频上传与图片上传没有多大区别,主要在我们对视频的处理,如截取某一帧作为封面图,获取视频时长等。 对视频处理我...

  • ‘SVideo’—使用MUI做视频上传第二弹

    之所以用“弹”不用“谈”,是弹弹弹... 在使用MUI来开发接近原生App的体验效果时,遇到很多坑。比如视频拍摄时...

  • 导影派部分视频案例展示

    更多视频请访问:上传优酷的部分视频 上传腾讯视频的部分视频

  • ‘SVideo’ UI第一版

    我们选择 DCould 的 MUI 框架来开发我们的‘SVideo’ APP,主要是因为能够速成 ^ _ ^。 我...

  • 直播技术栈

    直播技术栈 总体需求 上传/汇聚 视频编码 视频推流 URL拉取 API上传 上传加速 实时美颜 视频转码 实时转...

  • 二、ajax上传视频或者图片

    二。上传视频实例 这是还是基于thinkphp3.2 上传文件接口(视频),欢迎参考!!!

  • 使用iMovie导出App Store应用预览视频

    前言 最近公司应用更新需要上传App Store预览视频,结果在使用Safari上传预览视频时毫无反应,上传失败....

  • 尚硅谷大数据技术之Hive

    10.4.7 统计上传视频最多的用户Top10以及他们上传的观看次数在前20的视频思路: 先找到上传视频最多的10...

  • 使用AFN上传视频

    3年前有写过上传图片的文章,今天在这记录下上传视频的方法!上传图片和视频都属于文件上传(upload file),...

  • 分片视频上传

    对于facebook、twitter 上传视频api中,大视频都是需要分片上传,一次上传只能几Mb内, 并且是以 ...

网友评论

    本文标题:‘SVideo’视频上传

    本文链接:https://www.haomeiwen.com/subject/ohwygqtx.html