mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
rendering video thumbnail
This commit is contained in:
parent
5202a19b52
commit
ce5416210d
4
net/server/transform/transform_acopy.sh
Executable file
4
net/server/transform/transform_acopy.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
#ffmpeg -i $1 -y -f mp4 -map_metadata -1 -c:v copy -c:a copy $2
|
||||
#ffmpeg -f mp4 -i color=c=black:s=1280x720:r=5 -i $1 -crf 0 -c:a copy -shortest $2
|
||||
ffmpeg -i $1 -y -f mp3 -map_metadata -1 -c:a copy $2
|
3
net/server/transform/transform_icopy.sh
Executable file
3
net/server/transform/transform_icopy.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
convert -strip $1 -auto-orient $2
|
||||
|
3
net/server/transform/transform_ithumb.sh
Executable file
3
net/server/transform/transform_ithumb.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
convert -strip $1 -auto-orient -resize '640x640>' $2
|
||||
|
3
net/server/transform/transform_vcopy.sh
Executable file
3
net/server/transform/transform_vcopy.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
ffmpeg -i $1 -y -f mp4 -map_metadata -1 -c:v copy -c:a copy $2
|
||||
|
5
net/server/transform/transform_vthumb.sh
Executable file
5
net/server/transform/transform_vthumb.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
TMPFILE=$(mktemp /tmp/databag-XXXXX)
|
||||
ffmpeg -ss 0 -i $1 -y -vframes 1 -q:v 2 $TMPFILE.jpg
|
||||
convert -strip $TMPFILE.jpg -auto-orient -resize '640x640>' $2
|
@ -130,8 +130,8 @@ export function Carousel({ ready, items, itemRenderer, itemRemove }) {
|
||||
<Skeleton.Image style={{ height: 128 }} />
|
||||
</div>
|
||||
<div class="arrows">
|
||||
<div class="arrow" onClick={onRight}><RightOutlined style={{ visibility: scrollRight }} /></div>
|
||||
<div class="arrow" onClick={onLeft}><LeftOutlined style={{ visibility: scrollLeft }} /></div>
|
||||
<div class="arrow" onClick={onRight}><LeftOutlined style={{ visibility: 'hidden' }} /></div>
|
||||
<div class="arrow" onClick={onLeft}><RightOutlined style={{ visibility: 'hidden' }} /></div>
|
||||
</div>
|
||||
</CarouselWrapper>
|
||||
)
|
||||
@ -144,8 +144,8 @@ export function Carousel({ ready, items, itemRenderer, itemRemove }) {
|
||||
{slots}
|
||||
</div>
|
||||
<div class="arrows">
|
||||
<div class="arrow" onClick={onRight}><RightOutlined style={{ visibility: scrollRight }} /></div>
|
||||
<div class="arrow" onClick={onLeft}><LeftOutlined style={{ visibility: scrollLeft }} /></div>
|
||||
<div class="arrow" onClick={onRight}><LeftOutlined style={{ visibility: scrollRight }} /></div>
|
||||
<div class="arrow" onClick={onLeft}><RightOutlined style={{ visibility: scrollLeft }} /></div>
|
||||
</div>
|
||||
</CarouselWrapper>
|
||||
);
|
||||
|
@ -0,0 +1,8 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ReactPlayer from 'react-player'
|
||||
|
||||
export function AudioAsset({ label, audioUrl }) {
|
||||
|
||||
return <ReactPlayer height="100%" width="auto" controls="true" url={audioUrl} />
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ReactPlayer from 'react-player'
|
||||
import { TopicItemWrapper } from './TopicItem.styled';
|
||||
import ReactResizeDetector from 'react-resize-detector';
|
||||
import { useTopicItem } from './useTopicItem.hook';
|
||||
import { VideoAsset } from './VideoAsset/VideoAsset';
|
||||
import { AudioAsset } from './AudioAsset/AudioAsset';
|
||||
import { Avatar } from 'avatar/Avatar';
|
||||
import { CommentOutlined } from '@ant-design/icons';
|
||||
import { Carousel } from 'Carousel/Carousel';
|
||||
@ -18,13 +18,16 @@ export function TopicItem({ topic }) {
|
||||
|
||||
const renderAsset = (asset) => {
|
||||
if (asset.image) {
|
||||
return <img style={{ height: '100%', objectFit: 'container' }} src={actions.getAssetUrl(asset.image.full)} alt="" />
|
||||
if (asset.image.thumb) {
|
||||
return <img style={{ height: '100%', objectFit: 'contain' }} src={actions.getAssetUrl(asset.image.thumb)} alt="" />
|
||||
}
|
||||
return <img style={{ height: '100%', objectFit: 'contain' }} src={actions.getAssetUrl(asset.image.full)} alt="" />
|
||||
}
|
||||
if (asset.video) {
|
||||
return <ReactPlayer height="100%" width="auto" controls="true" url={actions.getAssetUrl(asset.video.full)} />
|
||||
return <VideoAsset thumbUrl={actions.getAssetUrl(asset.video.thumb)} videoUrl={actions.getAssetUrl(asset.video.full)} />
|
||||
}
|
||||
if (asset.audio) {
|
||||
return <ReactPlayer height="100%" width="auto" controls="true" url={actions.getAssetUrl(asset.audio.full)} />
|
||||
return <AudioAsset label={asset.audio.label} audioUrl={actions.getAssetUrl(asset.audio.full)} />
|
||||
}
|
||||
return <></>
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import ReactPlayer from 'react-player'
|
||||
import ReactResizeDetector from 'react-resize-detector';
|
||||
import { PlayCircleOutlined } from '@ant-design/icons';
|
||||
import { VideoAssetWrapper } from './VideoAsset.styled';
|
||||
|
||||
export function VideoAsset({ thumbUrl, videoUrl }) {
|
||||
|
||||
const [active, setActive] = useState(false);
|
||||
const [dimension, setDimension] = useState({});
|
||||
const [visibility, setVisibility] = useState('hidden');
|
||||
const [playing, setPlaying] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setActive(false);
|
||||
setVisibility('hidden');
|
||||
setPlaying(false);
|
||||
}, [thumbUrl, videoUrl]);
|
||||
|
||||
const onReady = () => {
|
||||
setVisibility('visible');
|
||||
setPlaying(true);
|
||||
}
|
||||
|
||||
if (!thumbUrl) {
|
||||
return <ReactPlayer height="100%" width="auto" controls="true" url={videoUrl} />
|
||||
}
|
||||
|
||||
const Player = () => {
|
||||
if (!active) {
|
||||
return (
|
||||
<div onClick={() => setActive(true)}>
|
||||
<PlayCircleOutlined style={{ fontSize: 48, color: '#eeeeee', cursor: 'pointer' }} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return <ReactPlayer style={{ visibility }} playing={playing} height="100%" width="100%" controls="true" url={videoUrl} onReady={onReady} />
|
||||
}
|
||||
|
||||
return (
|
||||
<VideoAssetWrapper>
|
||||
<ReactResizeDetector handleWidth={true} handleHeight={true}>
|
||||
{({ width, height }) => {
|
||||
if (width != dimension.width || height != dimension.height) {
|
||||
setDimension({ width, height });
|
||||
}
|
||||
return <img style={{ height: '100%', objectFit: 'contain' }} src={thumbUrl} alt="" />
|
||||
}}
|
||||
</ReactResizeDetector>
|
||||
<div class="player" style={{ width: dimension.width, height: dimension.height }}>
|
||||
<Player />
|
||||
</div>
|
||||
</VideoAssetWrapper>
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const VideoAssetWrapper = styled.div`
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
.player {
|
||||
top: 0;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -38,12 +38,13 @@ export async function addChannelTopic(token, channelId, message, assets ) {
|
||||
else if (asset.video) {
|
||||
const formData = new FormData();
|
||||
formData.append('asset', asset.video);
|
||||
let transform = encodeURIComponent(JSON.stringify(["vcopy;video"]));
|
||||
let transform = encodeURIComponent(JSON.stringify(["vcopy;video", 'vthumb;video']));
|
||||
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
|
||||
checkResponse(topicAsset);
|
||||
let assetEntry = await topicAsset.json();
|
||||
message.assets.push({
|
||||
video: {
|
||||
thumb: assetEntry.find(item => item.transform === 'vthumb;video').assetId,
|
||||
full: assetEntry.find(item => item.transform === 'vcopy;video').assetId,
|
||||
}
|
||||
});
|
||||
|
@ -39,12 +39,13 @@ export async function addContactChannelTopic(server, token, channelId, message,
|
||||
else if (asset.video) {
|
||||
const formData = new FormData();
|
||||
formData.append('asset', asset.video);
|
||||
let transform = encodeURIComponent(JSON.stringify(["vcopy;video"]));
|
||||
let transform = encodeURIComponent(JSON.stringify(["vcopy;video", "vthumb;video"]));
|
||||
let topicAsset = await fetch(`https://${server}/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&contact=${token}`, { method: 'POST', body: formData });
|
||||
checkResponse(topicAsset);
|
||||
let assetEntry = await topicAsset.json();
|
||||
message.assets.push({
|
||||
video: {
|
||||
thumb: assetEntry.find(item => item.transform === 'vthumb;video').assetId,
|
||||
full: assetEntry.find(item => item.transform === 'vcopy;video').assetId,
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user