WEB

랜딩페이지 비디오 나타내기

KyeongMin 2021. 3. 5. 17:22
728x90
반응형

비디오 Template 만들고

 

몽고DB에서 데이터 가져오고

 

가져온 비디오 데이터 스크린에 출력 Use map() methods

 

랜딩 페이지에서 우선 이거 만들고 

import React ,{useEffectfrom 'react'

 

    useEffect(() => {
     Axios.get('/api/video/getVideos')
     .then(respones=>{
         if(respones.data.success){

         }else{
             alert('비디오 가져오기를 실패 했습니다.')
         }
     })
    }, [])

라우터 생성을 위해 server의 video.js 부분으로 갑니다. 

routes/video.js 부분에

router.post('/getVideos',(req,res)=>{
    //비디오를 DB에서 가져와서 클라이언트에 보낸다. 
    Video.find()
    .populate('writer') //이populate를 써야 모든 정보를 가져온다. 
    .exec((err,videos)=>{
        if(err) return res.status(400).send(err);
        res.status(200).json({success: true, videos})
    })
})

이렇게뜨면 정상

 

혹시나 에러가 생길 수 있으니

const express = require('express');
const router = express.Router();
const { Video } = require("../models/Video");
const path = require("path");
const { auth } = require("../middleware/auth");
const multer = require("multer");
var ffmpeg = require("fluent-ffmpeg");

//storage multer config
let storage = multer.diskStorage({
    destination : (req,file,cb)=>{
        cb(null,"uploads/");
    },
    filename: (req, file, cb)=>{
        cb(null,'${Date.now()}_$file.originalname}');
    },
    fileFilter: (req,file,cb)=>{
        const ext = path.extname(file.originalname)
        if(ext!='.mp4'){
            return cb(res.status(400).end('only jpg, png, mp4 is allowed'),false);
        }
        cb(null,true)
    }
});
const upload = multer({storage: storage}).single("file");
//=================================
//             Video
//=================================
router.post('/uploadfiles',(req,res)=>{
    //비디오를 서버에 저장한다. 
    upload(req,res,err=>{
        if(err){
            return res.json({success: false, err})
        }
        return res.json({success: true,url: res.req.file.path, fileName: res.req.filename })
    })
})
router.post('/uploadVideo',(req,res)=>{
    //비디오를 정보를 저장한다. 
    const video=new Video(req.body)
    video.save((err,video)=>{
        if(err) return res.json({success: false, err})
        res.status(200).json({success: true})
    })
})
router.get("/getVideos", (req, res) => {
    //비디오를 DB에서 가져와서 클라이언트에 보낸다.
  
    Video.find()
      .populate('writer')
      .exec((err, videos) => {
        if (err) return res.status(400).send(err);
        res.status(200).json({ success: true, videos });
      })
  })
  
router.post('/thumbnail',(req,res)=>{
        //썸네일 생성 하고 비디오 러닝타임도 가져오기
        let filePath ="";
        let fileDuration ="";
        //비디오 정보 가져오기 
        ffmpeg.ffprobe(req.body.url, function(err, metadata){
            console.dir(metadata);
            console.log(metadata.format.duration);
            fileDuration = metadata.format.duration;
        });
    
        //썸네일 생성
        ffmpeg(req.body.url)
        .on('filenames', function (filenames) {//비디오 썸네일 파일 이름 생성
            console.log('Will generate ' + filenames.join(', '))
            console.log(filenames)
         filePath = "uploads/thumbnails/" + filenames[0];
        })
        .on('end', function () {//썸네일 생성한 후에 무엇을 할것 인지 
            console.log('Screenshots taken');
            return res.json({ success: true, url: filePath, fileDuration: fileDuration});
        })
        .on('error',function(err){
            console.error(err);
            return res.json({success: false, err});
        })
        .screenshots({
            // Will take screens at 20%, 40%, 60% and 80% of the video
            count: 3,
            folder: 'uploads/thumbnails',//이렇게 되어있으니 저번에 uploads폴더 안에 thumbnails폴더 생성
            size:'320x240',
            // %b input basename ( filename w/o extension )
            filename:'thumbnail-%b.png'
        })
})

module.exports = router;

참고하시고,

 

 

랜딩 페이지로 돌아가서

import React ,{useEffect,useStatefrom 'react'

 

선언

    const [VideosEtVideo] = useState([])

    useEffect(() => {
     Axios.get('/api/video/getVideos')
     .then(respones=>{
         if(respones.data.success){
            console.log(respones.data)
            setVideo(respones.data.Video)
         }else{
             alert('비디오 가져오기를 실패 했습니다.')
         }
     })
    }, [])

마무리 해주고

import moment from 'moment'

선언하고

 

import { Card,Icon,Avatar,Col,Typography,Row } from 'antd';
import Axios from 'axios';
import React ,{useEffect,useState} from 'react'
import moment from 'moment'
const { Title } = Typography
const { Meta}  = Card;

function LandingPage() {
    const [Video, setVideo] = useState([])
    useEffect(() => {
     Axios.get('/api/video/getVideos')
     .then(respones=>{
         if(respones.data.success){
            setVideo(respones.data.videos)
         }else{
             alert('비디오 가져오기를 실패 했습니다.')
         }
     })
    }, [])
    const renderCards =Video.map((video, index)=>{
        var minutes= Math.floor(video.duration/60);
        var seconds = Math.floor((video.duration-(minutes*60)));
                     {/*lg 6이면 4개의 화면 //md 8이니까 줄어들었을때 3개의 화면*/}
        return <Col key={index} lg={6} md={8} xs={24}>
            <a href = {`/video/post/${video._id}`}>
            <div style={{position: 'relative'}}>
                <img style={{width: '100%'}} src={`http://localhost:5000/${video.thumbnail}`} alt="thumbnail"/>
                <div className="duration">
                    <span>{minutes} : {seconds}</span>
                </div>
            </div>
        </a>
        <br/>
        <Meta
        avatar={
            <Avatar src={video.writer.image}/>
        }
        title ={Video.title}
        description=""                
        />
        <span>{video.writer.name}</span><br/>
        <span style={{marginLeft:'3rem'}}>{video.views} views</span> - <span>{moment(video.createdAt).format("MMM  Do YY")}</span>
        </Col>  
       
    }) 

    return (
       <div style={{width: '85%', margin: '3rem auto'}}>
           <Title level={2}>Recommended</Title>
           <hr/>
           <Row gutter={[32,16]}>
                {renderCards}
           </Row>
       </div>
    )
}

export default LandingPage

최종 소스이고

hoc / index.css 부분으로 가서

 

 

.duration{
  bottom : 0;
  right : 0;
  position: absolute;
  margin: 4px;
  color: #fff;
  background-color: rgba(17,17,17,0.8);
  opacity: 0.8;
  padding: 2px 4px;
  border-radius: 2px;
  letter-spacing: 0.5px;
  font-size: 12px;
  font-weight: 500;
  line-height: 12px;
}

 

추가합니다. 

 

이렇게

 

이렇게 크기에 따라 달라지는거죠.

728x90
반응형