Created
November 15, 2022 03:00
-
-
Save HectorBlisS/79ae2a7231e27adbeaed1629a2dd9934 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { json } from '@remix-run/node'; | |
import { Form, useActionData, useTransition } from '@remix-run/react'; | |
import { useEffect, useRef } from 'react'; | |
import useRecorder from '~/components/useRecorder'; | |
import fs from 'fs'; | |
export const action = async ({ request }) => { | |
const formData = await request.formData(); | |
const file = formData.get('audio'); | |
const ab = await file.arrayBuffer(); | |
const buf = Buffer.from(ab); | |
fs.writeFileSync('public/audioFiles/audio.webm', buf); | |
const form = Object.fromEntries(formData); | |
const errors = {}; | |
if (form.title === '') { | |
errors.title = 'Escribe un título'; | |
} | |
if (form.description === '') { | |
errors.description = 'Escribe una descripción'; | |
} | |
if (!Object.keys(errors).length) { | |
// TODO: guardar en la DB el path del file juntos title... | |
return { errors: {}, success: true, form }; | |
} else { | |
return json({ errors, form }, { status: 400 }); | |
} | |
}; | |
export default function Podcast() { | |
const data = useActionData(); | |
const transition = useTransition(); | |
const inputRef = useRef(); | |
const audioRef = useRef(); | |
const { blob, isRecording, audioURL, startRecording, stopRecording } = | |
useRecorder(); | |
const toggleRecording = () => { | |
if (isRecording) { | |
stopRecording(); | |
} else { | |
startRecording(); | |
} | |
}; | |
useEffect(() => { | |
if (blob && inputRef.current) { | |
const file = new File([blob], 'audio.webm'); | |
const dataTransfer = new DataTransfer(); | |
dataTransfer.items.add(file); | |
inputRef.current.files = dataTransfer.files; | |
} | |
}, [blob]); | |
console.log(transition); | |
return ( | |
<div className='grid place-items-center'> | |
<h2>Sube un episodio nuevo</h2> | |
{data?.success && ( | |
<h3 className='text-green-500'> | |
Tu episodio se ha guardado! correctamente!! | |
</h3> | |
)} | |
<audio src={audioURL} ref={audioRef} controls /> | |
<button | |
onClick={toggleRecording} | |
className={`rounded-full p-8 ${ | |
isRecording ? 'bg-red-500' : 'bg-blue-500' | |
}`} | |
> | |
{isRecording ? 'Grabando...' : 'Grabar'} | |
</button> | |
<Form method='post' encType='multipart/form-data'> | |
<input name='audio' ref={inputRef} type='file' /> | |
<p> | |
<label>Titulo del episodio</label> | |
<input | |
defaultValue={data?.form.title} | |
className='border' | |
type='text' | |
name='title' | |
placeholder='escribe el titulo' | |
/> | |
{data?.errors['title'] && ( | |
<p className='text-red-500 text-sm'>{data?.errors['title']}</p> | |
)} | |
</p> | |
<p> | |
<label>Descripción</label> | |
<textarea | |
defaultValue={data?.form.description} | |
className='border' | |
name='description' | |
></textarea> | |
{data?.errors['description'] && ( | |
<p className='text-red-500 text-sm'> | |
{data?.errors['description']} | |
</p> | |
)} | |
</p> | |
<button className='border p-4'> | |
{transition.state !== 'idle' ? 'Loading...' : 'Enviar'} | |
</button> | |
</Form> | |
</div> | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState } from 'react'; | |
const useRecorder = () => { | |
const [audioURL, setAudioURL] = useState(''); | |
const [isRecording, setIsRecording] = useState(false); | |
const [recorder, setRecorder] = useState(null); | |
const [blob, setBlob] = useState(null); | |
useEffect(() => { | |
if (!recorder) return; | |
if (isRecording) { | |
recorder.start(); | |
} else { | |
recorder.stop(); | |
} | |
const handleData = (e) => { | |
setAudioURL(URL.createObjectURL(e.data)); | |
setBlob(e.data); | |
}; | |
recorder.addEventListener('dataavailable', handleData); | |
return () => recorder.removeEventListener('dataavailable', handleData); | |
}, [recorder, isRecording]); | |
const startRecording = () => { | |
if (recorder === null) { | |
requestRecorder().then(setRecorder, console.error); | |
} | |
setIsRecording(true); | |
}; | |
const stopRecording = () => { | |
setIsRecording(false); | |
}; | |
return { blob, audioURL, isRecording, startRecording, stopRecording }; | |
}; | |
async function requestRecorder() { | |
const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); | |
return new MediaRecorder(stream); | |
} | |
export default useRecorder; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment