mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-25 07:47:56 -07:00
Add first pass of TTS read of steps in cook mode
This commit is contained in:
parent
93c2df41c3
commit
6c370f15c8
2 changed files with 97 additions and 1 deletions
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<span class="v-btn__content">
|
||||
<i v-if="!playing.value" aria-hidden="true" class="v-icon notranslate mdi mdi-play theme--dark" @click.stop="play"></i>
|
||||
<i v-if="playing.value" aria-hidden="true" class="v-icon notranslate mdi mdi-pause theme--dark" @click.stop="pause"></i>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onUnmounted } from "@nuxtjs/composition-api";
|
||||
import { RecipeStep } from "~/lib/api/types/recipe";
|
||||
import { NoUndefinedField } from "~/lib/api/types/non-generated";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
step: {
|
||||
type: Object as () => NoUndefinedField<RecipeStep>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup() {
|
||||
onUnmounted(() => {
|
||||
speechSynthesis.stop();
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
playing: false,
|
||||
played: false,
|
||||
utterance: null,
|
||||
currentIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
play() {
|
||||
const self = this;
|
||||
if (this.utterance && this.playing) {
|
||||
speechSynthesis.cancel();
|
||||
}
|
||||
|
||||
this.utterance = new SpeechSynthesisUtterance(this.step.text);
|
||||
this.utterance.onstart = (event) => {
|
||||
self.playing = true;
|
||||
// self.$emit("playing", true); // TODO: Consider if this event should bubble or a proxy of it should.
|
||||
|
||||
console.debug("Now playing: " + this.step.text);
|
||||
};
|
||||
this.utterance.onend = () => {
|
||||
self.playing = false;
|
||||
// self.$emit("playing", false);
|
||||
|
||||
console.debug("Playback complete");
|
||||
};
|
||||
|
||||
this.utterance.onpause = () => {
|
||||
self.playing = false;
|
||||
};
|
||||
|
||||
this.utterance.onresume = () => {
|
||||
self.playing = true;
|
||||
};
|
||||
|
||||
this.utterance.onboundary = (event) => {
|
||||
// Update the start of the current sentence.
|
||||
if (event.name === "sentence") {
|
||||
self.currentIndex = event.charIndex;
|
||||
}
|
||||
};
|
||||
// TODO: Evaluate the usefulness of this event.
|
||||
// this.utterance.onmark = (event) => {
|
||||
// console.log("mark")
|
||||
// console.log(event)
|
||||
// };
|
||||
this.utterance.onerror = (event) => {
|
||||
console.error("Error in playback")
|
||||
console.debug(event)
|
||||
};
|
||||
|
||||
speechSynthesis.speak(this.utterance);
|
||||
return true;
|
||||
},
|
||||
pause() {
|
||||
console.log("Stop playing");
|
||||
speechSynthesis.pause();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
</style>
|
|
@ -266,6 +266,7 @@
|
|||
<v-divider v-if="isCookMode && step.ingredientReferences && step.ingredientReferences.length > 0 && $vuetify.breakpoint.smAndUp" vertical ></v-divider>
|
||||
<v-col>
|
||||
<SafeMarkdown class="markdown" :source="step.text" />
|
||||
<RecipePageInstructionPlayer v-if="isCookMode" :step="step" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
|
@ -303,6 +304,7 @@ import { useExtractIngredientReferences } from "~/composables/recipe-page/use-ex
|
|||
import { NoUndefinedField } from "~/lib/api/types/non-generated";
|
||||
import DropZone from "~/components/global/DropZone.vue";
|
||||
import RecipeIngredients from "~/components/Domain/Recipe/RecipeIngredients.vue";
|
||||
import RecipePageInstructionPlayer from "~/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageInstructionPlayer.vue";
|
||||
interface MergerHistory {
|
||||
target: number;
|
||||
source: number;
|
||||
|
@ -315,7 +317,8 @@ export default defineComponent({
|
|||
draggable,
|
||||
RecipeIngredientHtml,
|
||||
DropZone,
|
||||
RecipeIngredients
|
||||
RecipeIngredients,
|
||||
RecipePageInstructionPlayer
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue