Skip to content
forked from Shirtiny/shWave

subtitles timeline and wave audio. 一个显示音频波形图并可编辑字幕的时间轴

Notifications You must be signed in to change notification settings

spring-xql/shWave

 
 

Repository files navigation

ShWave

npm NPM npm

NPM

Introduction

subtitles timeline and wave audio

Shwave is a subtitles timeline to help people build subtitles easily.

It also support audio-only.

Usage

REACT

npm i shwave -S
import { ShWave } from "shwave";

<ShWave
  duration={15}
  backgroundColor={"#529393"}
  currentTime={currentTime}
  throttleWait={1}
  url={videoUrl}
  waveColor={"#fbf8f86b"}
  alterWaveColor={"#57e3e3"}
  waveScale={0.8}
  click={onWaveClick}
  contextmenu={onWaveContextmenu}
  subArray={subArray}
  onSubMove={onSubMove}
  onSubMoveError={onSubMoveError}
/>;

Example

REACT

import React, { Fragment, useState, useCallback } from "react";
/** @jsx jsx */
import { css, jsx } from "@emotion/core";
import ShWave from "./componets/shwave";
import VideoPlayer from "./componets/videoPlayer";

const App = () => {
  const [player, setPlayer] = useState(null);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(15);
  const [url, setUrl] = useState("");
  const [subArray, setSubArray] = useState([
    {
      content: "content 1",
      end: 0.999,
      length: 0.999,
      start: 0,
    },
    {
      content: `content 2
      content 2 2
      content 2 4
      content 2 e
      content 2 e`,
      end: 6.999,
      length: 1.999,
      start: 5,
    },
    {
      content: `sdddddddddddddddddddddddddddddddddddd`,
      end: 14.999,
      length: 4.999,
      start: 10,
    },
    {
      content: "content 4",
      end: 18,
      length: 3,
      start: 15,
    },
  ]);

  const handleVideoFile = useCallback(
    (e) => {
      URL.revokeObjectURL(url);
      const file = e.currentTarget.files[0];
      const videoUrl = URL.createObjectURL(file);
      setUrl(videoUrl);
      const videoRegx = /^video\/(mp4|x-(flv))+$/;
      const found = file.type.match(videoRegx);
      const videoType =
        found && found[2] ? found[2] + "Custom" : found ? found[1] : "";
      player.switchVideo({
        url: videoUrl,
        type: videoType,
      });
    },
    [url, setUrl, player]
  );

  const contextmenu = useCallback(
    (time, event) => {
      if (!player) return;
      player.play();
      player.seek(time);
    },
    [player]
  );

  const click = useCallback(
    (time, event) => {
      if (!player) return;
      player.pause();
      player.seek(time);
    },
    [player]
  );

  const handleSubClick = useCallback((sub) => {
    console.log(sub);
  });

  const handleSubMove = useCallback((originSub, translateSecond) => {
    const subs = [...subArray];
    const index = subs.indexOf(originSub);
    const sub = { ...subs[index] };
    sub.start += translateSecond;
    sub.end += translateSecond;
    subs[index] = sub;
    console.log("update subArray");
    setSubArray(subs);
  });

  const handleSubMoveError = useCallback(() => {});

  const handleSubResize = useCallback((originSub, translateSecond, type) => {
    const subs = [...subArray];
    const index = subs.indexOf(originSub);
    const sub = { ...subs[index] };
    if (type === "start") {
      sub.start += translateSecond;
    } else {
      sub.end += translateSecond;
    }
    sub.length = sub.end - sub.start;
    subs[index] = sub;
    console.log("update subArray");
    setSubArray(subs);
  });

  const handleDurationChange = useCallback((duration) => {
    setDuration(duration);
    //pause the video
  });

  return (
    <Fragment>
      <div
        className="container"
        css={css`
          height: 600px;
          width: 600px;
        `}
      >
        <VideoPlayer
          url={url}
          player={player}
          setPlayer={setPlayer}
          setCurrentTime={setCurrentTime}
        />
        <input
          className="uploadVideo"
          type="file"
          name="file"
          onChange={handleVideoFile}
        />
        <input
          type="range"
          title={duration}
          value={duration}
          min="5"
          max="30"
          step="1"
          onChange={(e) => {
            handleDurationChange(Number(e.currentTarget.value));
          }}
        />
      </div>
      <div
        css={css`
          position: relative;
          height: 150px;
        `}
      >
        <ShWave
          duration={duration}
          backgroundColor="#529393"
          pointerColor="#ddd"
          pointerWidth={3}
          waveColor="#fbf8f86b"
          alterWaveColor="#57e3e3"
          waveScale={0.8}
          currentTime={currentTime}
          throttleWait={300}
          url={url}
          click={click}
          contextmenu={contextmenu}
          subArray={subArray}
          onSubClick={handleSubClick}
          onSubMove={handleSubMove}
          onSubMoveError={handleSubMoveError}
          ErrorWait={2000}
          ErrorColor="#f09b50d9"
          onSubResize={handleSubResize}
          subBlockClass="mySubBlockClass"
        />
      </div>
    </Fragment>
  );
};

export default App;

build

yarn
# yarn start
yarn pro

About

subtitles timeline and wave audio. 一个显示音频波形图并可编辑字幕的时间轴

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 95.2%
  • CSS 4.2%
  • HTML 0.6%