From b08165d7f18a77e1c693efd1bce316a7ea5b2700 Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Thu, 30 Sep 2021 16:12:40 +0200 Subject: [PATCH] Remove HTML video element --- backend/server/handlers.go | 6 ++-- backend/server/server.go | 2 +- backend/youtube/youtube.go | 12 ++----- frontend/src/Waveform.tsx | 65 ++++++++------------------------------ 4 files changed, 21 insertions(+), 64 deletions(-) diff --git a/backend/server/handlers.go b/backend/server/handlers.go index 5018723..597a914 100644 --- a/backend/server/handlers.go +++ b/backend/server/handlers.go @@ -47,8 +47,8 @@ func getThumbnails(c echo.Context) error { return c.File(mediaSet.ThumbnailPath()) } -// getVideo is a handler that responds with the video file for a MediaSet -func getVideo(c echo.Context) error { +// getAudio is a handler that responds with the audio file for a MediaSet +func getAudio(c echo.Context) error { videoID := c.Param("id") mediaSet := media.NewMediaSet(videoID) if err := mediaSet.Load(); err != nil { @@ -56,7 +56,7 @@ func getVideo(c echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError, "could not load media set") } - return c.File(mediaSet.VideoPath()) + return c.File(mediaSet.EncodedAudioPath()) } // getPeaks is a handler that returns a two-dimensional array of peaks, with diff --git a/backend/server/server.go b/backend/server/server.go index 0aa3084..e5d0254 100644 --- a/backend/server/server.go +++ b/backend/server/server.go @@ -24,7 +24,7 @@ func Start(opts Options) error { e.GET("/api/media_sets/:id", getMediaSet) e.GET("/api/media_sets/:id/thumbnails", getThumbnails) - e.GET("/api/media_sets/:id/video", getVideo) + e.GET("/api/media_sets/:id/audio", getAudio) e.GET("/api/media_sets/:id/peaks", getPeaks) return e.Start(opts.BindAddr) diff --git a/backend/youtube/youtube.go b/backend/youtube/youtube.go index ad3303c..606a4a7 100644 --- a/backend/youtube/youtube.go +++ b/backend/youtube/youtube.go @@ -87,7 +87,7 @@ func (d *Downloader) Download(ctx context.Context, videoID string) (*media.Media }() go func() { defer close(videoResultChan) - video, videoErr := d.downloadVideo(ctx, video, mediaSet.VideoPath(), mediaSet.ThumbnailPath()) + video, videoErr := d.downloadVideo(ctx, video, mediaSet.ThumbnailPath()) result := videoResult{video, videoErr} videoResultChan <- result wg.Done() @@ -197,7 +197,7 @@ func thumbnailGridSize(msecs int) (int, int) { return x, x } -func (d *Downloader) downloadVideo(ctx context.Context, video *youtubev2.Video, outPath, thumbnailOutPath string) (*media.Video, error) { +func (d *Downloader) downloadVideo(ctx context.Context, video *youtubev2.Video, thumbnailOutPath string) (*media.Video, error) { if len(video.Formats) == 0 { return nil, errors.New("error selecting audio format: no format available") } @@ -209,12 +209,6 @@ func (d *Downloader) downloadVideo(ctx context.Context, video *youtubev2.Video, return nil, fmt.Errorf("error fetching video stream: %v", err) } - videoFile, err := os.Create(outPath) - if err != nil { - return nil, fmt.Errorf("error creating video file: %v", err) - } - - streamReader := io.TeeReader(stream, videoFile) durationMsecs, err := strconv.Atoi(format.ApproxDurationMs) if err != nil { return nil, fmt.Errorf("could not parse video duration: %s", err) @@ -235,7 +229,7 @@ func (d *Downloader) downloadVideo(ctx context.Context, video *youtubev2.Video, "0", thumbnailOutPath, ) - cmd.Stdin = streamReader + cmd.Stdin = stream cmd.Stderr = &errOut if err = cmd.Run(); err != nil { diff --git a/frontend/src/Waveform.tsx b/frontend/src/Waveform.tsx index 9f04d8b..e2ead40 100644 --- a/frontend/src/Waveform.tsx +++ b/frontend/src/Waveform.tsx @@ -56,7 +56,6 @@ export const Waveform: React.FC = ({ audioContext }: Props) => { const [waveformPeaks, setWaveformPeaks] = useState(null); const [overviewPeaks, setOverviewPeaks] = useState(null); const hudCanvasRef = useRef(null); - const videoRef = useRef(null); // TODO: error handling const videoID = new URLSearchParams(window.location.search).get('video_id'); @@ -85,16 +84,11 @@ export const Waveform: React.FC = ({ audioContext }: Props) => { // setup player on page load: useEffect(() => { (async function () { - const video = videoRef.current; - if (video == null) { - return; - } - - video.addEventListener('timeupdate', () => { - setCurrentTime(video.currentTime); + audio.addEventListener('timeupdate', () => { + setCurrentTime(audio.currentTime); }); })(); - }); + }, []); // fetch mediaset on page load: useEffect(() => { @@ -139,16 +133,10 @@ export const Waveform: React.FC = ({ audioContext }: Props) => { return; } - const video = videoRef.current; - if (video == null) { - return; - } - - const url = `http://localhost:8888/api/media_sets/${videoID}/video`; - video.src = url; - video.muted = false; - video.volume = 1; - video.controls = true; + const url = `http://localhost:8888/api/media_sets/${videoID}/audio`; + audio.src = url; + audio.muted = false; + audio.volume = 1; }, [mediaSet]); // fetch new waveform peaks when zoom settings are updated: @@ -238,20 +226,11 @@ export const Waveform: React.FC = ({ audioContext }: Props) => { }; const handlePlay = async () => { - const video = videoRef.current; - if (video == null) { - return; - } - await video.play(); + await audio.play(); }; const handlePause = () => { - const video = videoRef.current; - if (video == null) { - return; - } - - video.pause(); + audio.pause(); }; const handleZoomIn = () => { @@ -281,14 +260,9 @@ export const Waveform: React.FC = ({ audioContext }: Props) => { }; const handleSelectionStart = (x: number) => { - const video = videoRef.current; - if (video == null) { - return; - } - const frame = canvasXToFrame(x, mediaSet.audio.frames); - if (video.paused) { - video.currentTime = frame / mediaSet.audio.sampleRate; + if (audio.paused) { + audio.currentTime = frame / mediaSet.audio.sampleRate; } }; @@ -304,18 +278,14 @@ export const Waveform: React.FC = ({ audioContext }: Props) => { }; setZoomSettings(settings); - const video = videoRef.current; - if (video == null) { - return; - } - video.currentTime = startFrame / mediaSet.audio.sampleRate; + audio.currentTime = startFrame / mediaSet.audio.sampleRate; }; // render component: const wrapperProps = { width: '90%', - height: '250px', + height: '550px', position: 'relative', margin: '0 auto', } as React.CSSProperties; @@ -342,17 +312,11 @@ export const Waveform: React.FC = ({ audioContext }: Props) => { zIndex: 1, } as React.CSSProperties; - const overviewStyles = { ...wrapperProps, height: '60px' }; + const overviewStyles = { ...wrapperProps, height: '120px' }; // TODO: why is the margin needed? const controlPanelStyles = { margin: '1em' } as React.CSSProperties; const clockTextAreaProps = { color: '#999', width: '400px' }; - const videoStyles = { - width: '30%', - height: 'auto', - margin: '10px auto 0 auto', - zIndex: 2, - } as React.CSSProperties; const thumbnailStyles = { width: '90%', height: '35px', @@ -362,7 +326,6 @@ export const Waveform: React.FC = ({ audioContext }: Props) => { return ( <> -