@@ -10,7 +10,7 @@ import CreationSvgIcon from '@mdi/svg/svg/creation.svg?raw'
1010import SummarizeSymbol from '@material-symbols/svg-700/outlined/summarize.svg?raw'
1111import TTSSymbol from '@material-symbols/svg-700/outlined/text_to_speech.svg?raw'
1212import STTSymbol from '@material-symbols/svg-700/outlined/speech_to_text.svg?raw'
13- import { VALID_AUDIO_MIME_TYPES , VALID_TEXT_MIME_TYPES } from '../constants.js'
13+ import { VALID_AUDIO_MIME_TYPES , VALID_TEXT_MIME_TYPES , VALID_VIDEO_MIME_TYPES } from '../constants.js'
1414
1515const actionIgnoreLists = [
1616 'trashbin' ,
@@ -156,6 +156,45 @@ function registerSttAction() {
156156 registerFileAction ( sttAction )
157157}
158158
159+ function registerSttSubtitlesAction ( ) {
160+ const sttSubtitlesAction = {
161+ id : 'assistant-stt-subtitles' ,
162+ parent : 'assistant-group' ,
163+ displayName : ( { nodes } ) => {
164+ return t ( 'assistant' , 'Generate subtitles using AI' )
165+ } ,
166+ enabled ( { nodes, view } ) {
167+ return ! actionIgnoreLists . includes ( view . id )
168+ && nodes . length === 1
169+ && ! nodes . some ( ( { permissions } ) => ( permissions & Permission . READ ) === 0 )
170+ && nodes . every ( ( { type } ) => type === FileType . File )
171+ && nodes . every ( ( { mime } ) => VALID_AUDIO_MIME_TYPES . includes ( mime ) || VALID_VIDEO_MIME_TYPES . includes ( mime ) )
172+ } ,
173+ iconSvgInline : ( ) => STTSymbol ,
174+ order : 0 ,
175+ async exec ( { nodes } ) {
176+ const node = nodes [ 0 ]
177+ const { default : axios } = await import ( '@nextcloud/axios' )
178+ const { generateOcsUrl } = await import ( '@nextcloud/router' )
179+ const { showError, showSuccess } = await import ( '@nextcloud/dialogs' )
180+ const url = generateOcsUrl ( '/apps/assistant/api/v1/file-action/{fileId}/core:audio2text:subtitles' , { fileId : node . fileid } )
181+ try {
182+ await axios . post ( url )
183+ showSuccess (
184+ t ( 'assistant' , 'AI subtitles task submitted successfully.' ) + '\n'
185+ + t ( 'assistant' , 'You will be notified when it is ready.' ) + '\n'
186+ + t ( 'assistant' , 'It can also be checked in the Assistant in the "Work with audio -> Generate subtitles" menu.' ) ,
187+ )
188+ } catch ( error ) {
189+ console . error ( error )
190+ showError ( t ( 'assistant' , 'Failed to launch the AI file action' ) )
191+ }
192+ return null
193+ } ,
194+ }
195+ registerFileAction ( sttSubtitlesAction )
196+ }
197+
159198const assistantEnabled = loadState ( 'assistant' , 'assistant-enabled' , false )
160199const summarizeAvailable = loadState ( 'assistant' , 'summarize-available' , false )
161200const sttAvailable = loadState ( 'assistant' , 'stt-available' , false )
@@ -174,6 +213,7 @@ if (assistantEnabled) {
174213 }
175214 if ( sttAvailable ) {
176215 registerSttAction ( )
216+ registerSttSubtitlesAction ( )
177217 }
178218 if ( summarizeAvailable ) {
179219 registerSummarizeAction ( )
0 commit comments