Basic loading of videos

ElementalAlchemist 3 weeks ago
parent 6608555a8b
commit 89ff17564e

@ -8,4 +8,4 @@
.streamTimeSettingLabel {
margin-right: 3px;
}
}

@ -1,4 +1,5 @@
import { Accessor, Component, createSignal, Setter, Show } from "solid-js";
import { Accessor, Component, createEffect, createSignal, Setter, Show } from "solid-js";
import Hls from "hls.js";
import { DateTime } from "luxon";
import {
TimeType,
@ -8,6 +9,8 @@ import {
} from "./convertTime";
import styles from "./video.module.scss";
Hls.DefaultConfig.maxBufferHole = 600;
export const VIDEO_FRAMES_PER_SECOND = 30;
export const PLAYBACK_RATES = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4, 8];
@ -177,3 +180,28 @@ export const KeyboardShortcuts: Component<KeyboardShortcutProps> = (
</details>
);
};
export interface VideoPlayerProps {
videoURL: string;
errorList: Accessor<string[]>;
setErrorList: Setter<string[]>;
videoPlayer: Accessor<Hls>;
}
export const VideoPlayer: Component<VideoPlayerProps> = (props) => {
if (!Hls.isSupported()) {
const newError =
"Your browser doesn't support MediaSource extensions. Video playback and editing won't work.";
props.setErrorList([...props.errorList(), newError]);
return <></>;
}
let videoElement;
createEffect(() => {
if (videoElement) {
props.videoPlayer().attachMedia(videoElement);
}
});
return <video ref={videoElement} controls={true}></video>;
};

@ -1,3 +1,8 @@
.hidden {
display: none;
}
video {
max-width: 100%;
max-height: 50vh;
}

@ -1,8 +1,23 @@
import { Accessor, Component, createResource, createSignal, For, Show, Suspense } from "solid-js";
import {
Accessor,
Component,
createResource,
createSignal,
For,
Setter,
Show,
Suspense,
} from "solid-js";
import Hls from "hls.js";
import { DateTime } from "luxon";
import styles from "./Restreamer.module.scss";
import { dateTimeFromWubloaderTime } from "../common/convertTime";
import { KeyboardShortcuts, StreamTimeSettings, StreamVideoInfo } from "../common/video";
import { dateTimeFromWubloaderTime, wubloaderTimeFromDateTime } from "../common/convertTime";
import {
KeyboardShortcuts,
StreamTimeSettings,
StreamVideoInfo,
VideoPlayer,
} from "../common/video";
export interface DefaultsData {
video_channel: string;
@ -51,7 +66,11 @@ export const Restreamer: Component = () => {
</div>
<Suspense>
<Show when={defaultsData()}>
<RestreamerWithDefaults defaults={defaultsData()} />
<RestreamerWithDefaults
defaults={defaultsData()}
errorList={pageErrors}
setErrorList={setPageErrors}
/>
</Show>
</Suspense>
</>
@ -60,6 +79,8 @@ export const Restreamer: Component = () => {
interface RestreamerDefaultProps {
defaults: DefaultsData;
errorList: Accessor<string[]>;
setErrorList: Setter<string[]>;
}
const RestreamerWithDefaults: Component<RestreamerDefaultProps> = (props) => {
@ -72,6 +93,26 @@ const RestreamerWithDefaults: Component<RestreamerDefaultProps> = (props) => {
streamEndTime: null,
});
const [videoPlayer, setVideoPlayer] = createSignal(new Hls());
const videoURL = () => {
const streamInfo = streamVideoInfo();
const startTime = wubloaderTimeFromDateTime(streamInfo.streamStartTime);
const query = new URLSearchParams({ start: startTime });
if (streamInfo.streamEndTime) {
const endTime = wubloaderTimeFromDateTime(streamInfo.streamEndTime);
query.append("end", endTime);
}
const queryString = query.toString();
let url = `/playlist/${streamInfo.streamName}.m3u8`;
if (queryString !== "") {
url += `?${queryString}`;
}
return url;
};
videoPlayer().loadSource(videoURL());
return (
<>
<StreamTimeSettings
@ -80,6 +121,12 @@ const RestreamerWithDefaults: Component<RestreamerDefaultProps> = (props) => {
setStreamVideoInfo={setStreamVideoInfo}
showTimeRangeLink={false}
/>
<VideoPlayer
videoURL={videoURL()}
errorList={props.errorList}
setErrorList={props.setErrorList}
videoPlayer={videoPlayer}
/>
</>
);
};

@ -334,7 +334,9 @@ const ThumbnailManager: Component = () => {
</div>
<div>
<button type="submit">Submit</button>
<button type="button" onClick={(event) => setEditing(false)}>Cancel</button>
<button type="button" onClick={(event) => setEditing(false)}>
Cancel
</button>
<ul class={styles.templateUpdateErrors}>
<For each={formErrors()}>
{(error: string, index: Accessor<number>) => <li>{error}</li>}

Loading…
Cancel
Save