diff --git a/net/server/transform/transform_acopy.sh b/net/server/transform/transform_acopy.sh new file mode 100755 index 00000000..7c696e83 --- /dev/null +++ b/net/server/transform/transform_acopy.sh @@ -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 diff --git a/net/server/transform/transform_icopy.sh b/net/server/transform/transform_icopy.sh new file mode 100755 index 00000000..ac13f2aa --- /dev/null +++ b/net/server/transform/transform_icopy.sh @@ -0,0 +1,3 @@ +#!/bin/bash +convert -strip $1 -auto-orient $2 + diff --git a/net/server/transform/transform_ithumb.sh b/net/server/transform/transform_ithumb.sh new file mode 100755 index 00000000..51561afd --- /dev/null +++ b/net/server/transform/transform_ithumb.sh @@ -0,0 +1,3 @@ +#!/bin/bash +convert -strip $1 -auto-orient -resize '640x640>' $2 + diff --git a/net/server/transform/transform_vcopy.sh b/net/server/transform/transform_vcopy.sh new file mode 100755 index 00000000..b71c4c33 --- /dev/null +++ b/net/server/transform/transform_vcopy.sh @@ -0,0 +1,3 @@ +#!/bin/bash +ffmpeg -i $1 -y -f mp4 -map_metadata -1 -c:v copy -c:a copy $2 + diff --git a/net/server/transform/transform_vthumb.sh b/net/server/transform/transform_vthumb.sh new file mode 100755 index 00000000..b7930c9a --- /dev/null +++ b/net/server/transform/transform_vthumb.sh @@ -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 diff --git a/net/web/src/Carousel/Carousel.jsx b/net/web/src/Carousel/Carousel.jsx index e3f74df7..fa736147 100644 --- a/net/web/src/Carousel/Carousel.jsx +++ b/net/web/src/Carousel/Carousel.jsx @@ -130,8 +130,8 @@ export function Carousel({ ready, items, itemRenderer, itemRemove }) {
-
-
+
+
) @@ -144,8 +144,8 @@ export function Carousel({ ready, items, itemRenderer, itemRemove }) { {slots}
-
-
+
+
); diff --git a/net/web/src/User/Conversation/TopicItem/AudioAsset/AudioAsset.jsx b/net/web/src/User/Conversation/TopicItem/AudioAsset/AudioAsset.jsx new file mode 100644 index 00000000..163ee7cb --- /dev/null +++ b/net/web/src/User/Conversation/TopicItem/AudioAsset/AudioAsset.jsx @@ -0,0 +1,8 @@ +import React, { useEffect, useState } from 'react'; +import ReactPlayer from 'react-player' + +export function AudioAsset({ label, audioUrl }) { + + return +} + diff --git a/net/web/src/User/Conversation/TopicItem/TopicItem.jsx b/net/web/src/User/Conversation/TopicItem/TopicItem.jsx index e1aa8d3e..9589c19b 100644 --- a/net/web/src/User/Conversation/TopicItem/TopicItem.jsx +++ b/net/web/src/User/Conversation/TopicItem/TopicItem.jsx @@ -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 + if (asset.image.thumb) { + return + } + return } if (asset.video) { - return + return } if (asset.audio) { - return + return } return <> } diff --git a/net/web/src/User/Conversation/TopicItem/VideoAsset/VideoAsset.jsx b/net/web/src/User/Conversation/TopicItem/VideoAsset/VideoAsset.jsx new file mode 100644 index 00000000..c9c3c371 --- /dev/null +++ b/net/web/src/User/Conversation/TopicItem/VideoAsset/VideoAsset.jsx @@ -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 + } + + const Player = () => { + if (!active) { + return ( +
setActive(true)}> + +
+ ) + } + return + } + + return ( + + + {({ width, height }) => { + if (width != dimension.width || height != dimension.height) { + setDimension({ width, height }); + } + return + }} + +
+ +
+
+ ) +} + diff --git a/net/web/src/User/Conversation/TopicItem/VideoAsset/VideoAsset.styled.js b/net/web/src/User/Conversation/TopicItem/VideoAsset/VideoAsset.styled.js new file mode 100644 index 00000000..3afbc638 --- /dev/null +++ b/net/web/src/User/Conversation/TopicItem/VideoAsset/VideoAsset.styled.js @@ -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; + } +`; + + diff --git a/net/web/src/api/addChannelTopic.js b/net/web/src/api/addChannelTopic.js index 5754f031..50ee1faa 100644 --- a/net/web/src/api/addChannelTopic.js +++ b/net/web/src/api/addChannelTopic.js @@ -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, } }); diff --git a/net/web/src/api/addContactChannelTopic.js b/net/web/src/api/addContactChannelTopic.js index 6d0911fc..ffdcdb54 100644 --- a/net/web/src/api/addContactChannelTopic.js +++ b/net/web/src/api/addContactChannelTopic.js @@ -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, } });