Skip to content

Commit

Permalink
Merge pull request #958 from Arnei/subtitles-as-tracks-with-tags
Browse files Browse the repository at this point in the history
Change subtitle identification from flavor to id
  • Loading branch information
mliradelc authored Aug 31, 2023
2 parents 7b1c958 + 994ec1e commit 72dedf2
Show file tree
Hide file tree
Showing 17 changed files with 313 additions and 187 deletions.
17 changes: 10 additions & 7 deletions editor-settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,21 @@
#mainFlavor = "captions"

[subtitles.languages]
## A list of languages for which subtitles can be created
"captions/source+de" = "Deutsch"
"captions/source+en" = "English"
"captions/source+es" = "Español"
## A list of languages for which new subtitles can be created
# For each language, various tags can be specified
# A list of officially recommended tags can be found at: TODO: link to opencast documentation for subtitle tags
# At least the "lang" tag MUST be specified
german = { lang = "de-DE" }
english = { lang = "en-US", type = "closed-caption" }
spanish = { lang = "es" }

[subtitles.icons]
# A list of icons to be displayed for languages defined above.
# Values are strings but should preferably be Unicode icons.
# These are optional and you can also choose to have no icons.
"captions/source+de" = "🇩🇪"
"captions/source+en" = "🇺🇸"
"captions/source+es" = "🇪🇸"
"de-DE" = "🇩🇪"
"en-US" = "🇺🇸"
"es" = "🇪🇸"

[subtitles.defaultVideoFlavor]
# Specify the default video in the subtitle video player by flavor
Expand Down
60 changes: 35 additions & 25 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"redux": "^4.2.1",
"standardized-audio-context": "^25.3.55",
"typescript": "^4.9.5",
"uuid": "^9.0.0",
"webvtt-parser": "^2.2.0"
},
"scripts": {
Expand Down Expand Up @@ -82,6 +83,7 @@
"@types/react-resizable": "^3.0.4",
"@types/react-virtualized-auto-sizer": "^1.0.1",
"@types/react-window": "^1.8.5",
"@types/uuid": "^9.0.0",
"use-resize-observer": "^9.1.0"
}
}
14 changes: 7 additions & 7 deletions public/editor-settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ show = true
mainFlavor = "captions"

[subtitles.languages]
"captions/source+de" = "Deutsch"
"captions/source+en" = "English"
"captions/source+es" = "Español"
"captions/source" = "Generic"
german = { lang = "de-DE" }
english = { lang = "en-US", type = "closed-caption" }
spanish = { lang = "es" }


[subtitles.icons]
"captions/source+de" = "🇩🇪"
"captions/source+en" = "🇺🇸"
"captions/source+es" = "🇪🇸"
"de-DE" = "🇩🇪"
"en-US" = "🇺🇸"
"es" = "🇪🇸"

[thumbnail]
show = true
11 changes: 9 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export interface configureFieldsAttributes {
readonly: boolean,
}

export interface subtitleTags {
lang: string,
'auto-generated': string,
'auto-generator': string,
type: string,
}

/**
* Settings interface
*/
Expand All @@ -54,7 +61,7 @@ interface iSettings {
subtitles: {
show: boolean,
mainFlavor: string,
languages: { [key: string]: string } | undefined,
languages: { [key: string]: subtitleTags } | undefined,
icons: { [key: string]: string } | undefined,
defaultVideoFlavor: Flavor | undefined,
}
Expand Down Expand Up @@ -366,7 +373,7 @@ const SCHEMA = {
subtitles: {
show: types.boolean,
mainFlavor: types.string,
languages: types.map,
languages: types.objectsWithinObjects,
icons: types.map,
defaultVideoFlavor: types.map,
},
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@
"backButton-tooltip": "Return to subtitle selection",
"editTitle": "Subtitle Editor - {{title}}",
"editTitle-loading": "Loading",
"generic": "Generic"
"generic": "Generic",
"autoGenerated": "Auto-generated"
},

"subtitleList": {
Expand Down
9 changes: 5 additions & 4 deletions src/main/Save.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import { postMetadata, selectPostError, selectPostStatus, setHasChanges as metad
import { selectSubtitles, selectHasChanges as selectSubtitleHasChanges,
setHasChanges as subtitleSetHasChanges } from "../redux/subtitleSlice";
import { serializeSubtitle } from "../util/utilityFunctions";
import { Flavor } from "../types";
import { selectTheme } from "../redux/themeSlice";
import { ThemedTooltip } from "./Tooltip";

Expand Down Expand Up @@ -142,9 +141,11 @@ export const SaveButton: React.FC = () => {
const subtitlesForPosting = []

for (const identifier in subtitles) {
const flavor: Flavor = {type: identifier.split("/")[0], subtype: identifier.split("/")[1]}
subtitlesForPosting.push({flavor: flavor, subtitle: serializeSubtitle(subtitles[identifier])})

subtitlesForPosting.push({
id: identifier,
subtitle: serializeSubtitle(subtitles[identifier].cues),
tags: subtitles[identifier].tags
})
}
return subtitlesForPosting
}
Expand Down
32 changes: 17 additions & 15 deletions src/main/SubtitleEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,23 @@ import { basicButtonStyle, flexGapReplacementStyle } from "../cssStyles";
import { faChevronLeft } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
selectCaptionTrackByFlavor,
selectSubtitlesFromOpencastById,
} from '../redux/videoSlice'
import { useDispatch, useSelector } from "react-redux";
import { SubtitleCue } from "../types";
import SubtitleListEditor from "./SubtitleListEditor";
import {
setIsDisplayEditView,
selectSelectedSubtitleByFlavor,
selectSelectedSubtitleFlavor,
selectSelectedSubtitleById,
selectSelectedSubtitleId,
setSubtitle
} from '../redux/subtitleSlice'
import { settings } from "../config";
import SubtitleVideoArea from "./SubtitleVideoArea";
import SubtitleTimeline from "./SubtitleTimeline";
import { useTranslation } from "react-i18next";
import { selectTheme } from "../redux/themeSlice";
import { parseSubtitle } from "../util/utilityFunctions";
import { ThemedTooltip } from "./Tooltip";
import { generateButtonTitle } from "./SubtitleSelect";

/**
* Displays an editor view for a selected subtitle file
Expand All @@ -32,17 +31,17 @@ const SubtitleEditor : React.FC = () => {

const dispatch = useDispatch()
const [getError, setGetError] = useState<string | undefined>(undefined)
const subtitle : SubtitleCue[] = useSelector(selectSelectedSubtitleByFlavor)
const selectedFlavor = useSelector(selectSelectedSubtitleFlavor)
const captionTrack = useSelector(selectCaptionTrackByFlavor(selectedFlavor))
const subtitle = useSelector(selectSelectedSubtitleById)
const selectedId = useSelector(selectSelectedSubtitleId)
const captionTrack = useSelector(selectSubtitlesFromOpencastById(selectedId))
const theme = useSelector(selectTheme)

// Prepare subtitle in redux
useEffect(() => {
// Parse subtitle data from Opencast
if (subtitle === undefined && captionTrack !== undefined && captionTrack.subtitle !== undefined && selectedFlavor) {
if (subtitle?.cues === undefined && captionTrack !== undefined && captionTrack.subtitle !== undefined && selectedId) {
try {
dispatch(setSubtitle({identifier: selectedFlavor, subtitles: parseSubtitle(captionTrack.subtitle)}))
dispatch(setSubtitle({identifier: selectedId, subtitles: { cues: parseSubtitle(captionTrack.subtitle), tags: captionTrack.tags } }))
} catch (error) {
if (error instanceof Error) {
setGetError(error.message)
Expand All @@ -52,15 +51,18 @@ const SubtitleEditor : React.FC = () => {
}

// Or create a new subtitle instead
} else if (subtitle === undefined && captionTrack === undefined && selectedFlavor) {
} else if (subtitle?.cues === undefined && captionTrack === undefined && selectedId) {
// Create an empty subtitle
dispatch(setSubtitle({identifier: selectedFlavor, subtitles: []}))
dispatch(setSubtitle({identifier: selectedId, subtitles: { cues: [], tags: [] }}))
}
}, [dispatch, captionTrack, subtitle, selectedFlavor])
}, [dispatch, captionTrack, subtitle, selectedId])

const getTitle = () => {
return (settings.subtitles.languages !== undefined && subtitle && selectedFlavor) ?
settings.subtitles.languages[selectedFlavor] : t("subtitles.editTitle-loading")
if (subtitle) {
return generateButtonTitle(subtitle.tags, t)
} else {
return t("subtitles.editTitle-loading")
}
}

const subtitleEditorStyle = css({
Expand Down
Loading

0 comments on commit 72dedf2

Please sign in to comment.