Compare commits

...

2 Commits

Author SHA1 Message Date
Nicky Dev
44ad695823 feat: The manual stream allows updating the Recording URL 2023-10-04 14:47:55 +07:00
Nicky Dev
8a0a722a33 feat: Support more recording URL format 2023-10-04 14:46:16 +07:00
2 changed files with 36 additions and 25 deletions

View File

@ -1,5 +1,5 @@
import { useMemo, useState } from "react";
import ReactPlayer from 'react-player'
import ReactPlayer from "react-player";
export enum VideoStatus {
Online = "online",
@ -21,29 +21,21 @@ export function LiveVideoPlayer(props: VideoPlayerProps) {
<div className={status}>
<div>{status}</div>
</div>
<ReactPlayer
autoPlay
playing={true}
className='video-player'
url={streamCached}
width='100%'
height='100%'
controls={true}
playsinline={true}
light={<img src={props.poster}
alt='Thumbnail'
style={{
maxHeight:"100%",
maxWidth:'100%'
}}
/>}
onProgress={()=>{
setStatus(VideoStatus.Online);
}}
onError={()=>{
<ReactPlayer
controls
playing
url={streamCached}
config={{ file: { attributes: { poster: props.poster } } }}
className="video-player"
width="100%"
height="100%"
onStart={() => setStatus(VideoStatus.Online)}
onError={(type, error) => {
if (error?.type === "networkError") {
setStatus(VideoStatus.Offline);
}}
/>
}
}}
/>
</div>
);
}

View File

@ -11,6 +11,7 @@ import { findTag } from "../utils";
import { useLogin } from "hooks/login";
import { NewGoalDialog } from "element/new-goal";
import { useGoals } from "hooks/goals";
import ReactPlayer from "react-player";
export interface StreamEditorProps {
ev?: NostrEvent;
@ -52,6 +53,7 @@ export function StreamEditor({ ev, onFinish, options }: StreamEditorProps) {
const [summary, setSummary] = useState("");
const [image, setImage] = useState("");
const [stream, setStream] = useState("");
const [record, setRecord] = useState("");
const [status, setStatus] = useState("");
const [start, setStart] = useState<string>();
const [tags, setTags] = useState<string[]>([]);
@ -66,6 +68,7 @@ export function StreamEditor({ ev, onFinish, options }: StreamEditorProps) {
setSummary(findTag(ev, "summary") ?? "");
setImage(findTag(ev, "image") ?? "");
setStream(findTag(ev, "streaming") ?? "");
setRecord(findTag(ev, "recording") ?? "");
setStatus(findTag(ev, "status") ?? StreamState.Live);
setStart(findTag(ev, "starts"));
setTags(ev?.tags.filter(a => a[0] === "t").map(a => a[1]) ?? []);
@ -80,15 +83,18 @@ export function StreamEditor({ ev, onFinish, options }: StreamEditorProps) {
if (stream.length < 5 || !stream.match(/^https?:\/\/.*\.m3u8?$/i)) {
return false;
}
if (record.length > 0 && !ReactPlayer.canPlay(record)) {
return false;
}
if (image.length > 0 && !image.match(/^https?:\/\//i)) {
return false;
}
return true;
}, [title, image, stream]);
}, [title, image, stream, record]);
useEffect(() => {
setIsValid(ev !== undefined || validate());
}, [validate, title, summary, image, stream]);
}, [ev, validate]);
async function publishStream() {
const pub = login?.publisher();
@ -106,6 +112,9 @@ export function StreamEditor({ ev, onFinish, options }: StreamEditorProps) {
.tag(["streaming", stream])
.tag(["status", status])
.tag(["starts", starts]);
if (record) {
eb.tag(["recording", record]);
}
if (status === StreamState.Ended) {
eb.tag(["ends", ends]);
}
@ -217,6 +226,16 @@ export function StreamEditor({ ev, onFinish, options }: StreamEditorProps) {
</div>
</div>
)}
{status === StreamState.Ended && (
<div>
<p>
<FormattedMessage defaultMessage="Recording URL" />
</p>
<div className="paper">
<input type="text" placeholder="https://" value={record} onChange={e => setRecord(e.target.value)} />
</div>
</div>
)}
</>
)}
{(options?.canSetTags ?? true) && (