Skip to content

Commit

Permalink
You are now able to change the session info, while uploading
Browse files Browse the repository at this point in the history
  • Loading branch information
xannyxs committed Feb 28, 2024
1 parent ec3a017 commit 95ef4bf
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 55 deletions.
8 changes: 2 additions & 6 deletions packages/app/app/api/upload-video/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ export async function POST(request: NextRequest) {
try {
const data = await request.formData()
const video: File | null = data.get('file') as unknown as File
const url: string | null = data.get('url') as unknown as string

if (!video) {
return NextResponse.json({ success: false, status: 400 })
}

const livepeer = new Livepeer({
apiKey: process.env.LIVEPEER_API_KEY,
})

const asset = await livepeer.asset.create({ name: video.name })
const response = await fetch(asset.object!.url, {
const response = await fetch(url, {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.LIVEPEER_API_KEY}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@ import { createSessionAction } from '@/lib/actions/sessions'
import { type IExtendedEvent } from '@/lib/types'
import { Progress } from '@/components/ui/progress'
import { IStageModel } from 'streameth-new-server/src/interfaces/stage.interface'
import { getUrlAction } from '@/lib/actions/livepeer'
import type { ISession } from 'streameth-new-server/src/interfaces/session.interface'

const performUpload = (
video: File,
url: string,
abortControllerRef: MutableRefObject<AbortController>,
onProgress: (percentage: number) => void
) => {
const formData = new FormData()
formData.append('file', video)
formData.append('url', url)

const xhr = new XMLHttpRequest()

Expand Down Expand Up @@ -67,26 +71,34 @@ const Dropzone = ({

const [progress, setProgress] = useState<number>(0)
const [selectedFile, setSelectedFile] = useState<File | null>(null)
const [session, setSession] = useState<ISession | null>(null)

const handleUpload = async (file: File) => {
setSelectedFile(file)

await createSessionAction({
const asset = await getUrlAction(file.name)
const session = await createSessionAction({
session: {
name: 'No Name',
description: 'No Description',
eventId: event._id,
organizationId: event.organizationId,
speakers: [],
stageId: stages[0]._id!,
assetId: asset?.assetId,
start: 0,
end: 0,
},
})
setSelectedFile(file)
setSession(session)
console.log('Uploading video...')
performUpload(file, abortControllerRef, (percentage) => {
setProgress(percentage)
})
performUpload(
file,
asset?.url!,
abortControllerRef,
(percentage) => {
setProgress(percentage)
}
)
}

const onDrop = useCallback((acceptedFiles: File[]) => {
Expand All @@ -106,14 +118,15 @@ const Dropzone = ({

const handleCancel = () => {
setProgress(0)
setSession(null)
setSelectedFile(null)
abortControllerRef.current.abort()
abortControllerRef.current = new AbortController()
}

return (
<div className="flex flex-col justify-center items-center p-4 w-full h-full">
{!selectedFile ? (
{!selectedFile && !session ? (
<div>
<p className="flex justify-center mb-3 text-xl">
You are about to upload to the event:&nbsp;
Expand All @@ -139,15 +152,23 @@ const Dropzone = ({
</div>
) : (
<div className="flex flex-col justify-center items-center">
<UploadVideoForm />
<span className="mt-2 font-medium">{progress}%</span>
<Progress value={progress} className="mt-1 mb-4" />
<Alert
triggerText="Cancel upload..."
dialogTitle="Are you sure to cancel the upload?"
dialogDescription=""
continueClick={() => handleCancel()}
/>
{session && (
<UploadVideoForm session={session} progress={progress} />
)}
{progress < 100 ? (
<>
<span className="mt-2 font-medium">{progress}%</span>
<Progress value={progress} className="mt-1 mb-4" />
<Alert
triggerText="Cancel upload..."
dialogTitle="Are you sure to cancel the upload?"
dialogDescription=""
continueClick={() => handleCancel()}
/>
</>
) : (
<div className="mt-2">Finished upload</div> // TODO: Button to go to video
)}
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { sessionSchema, videoUploadSchema } from '@/lib/schema'
import { videoUploadSchema } from '@/lib/schema'
import { toast } from 'sonner'
import { Loader2 } from 'lucide-react'
import ImageUpload from '@/components/misc/form/imageUpload'
Expand All @@ -26,8 +26,17 @@ import { apiUrl } from '@/lib/utils/utils'
import InfoHoverCard from '@/components/misc/interact/InfoHoverCard'
import { getCookie, hasCookie } from '@/lib/actions/cookieConsent'
import { fetchSession } from '@/lib/services/sessionService'
import { getAssetAction } from '@/lib/actions/livepeer'
import { ISession } from 'streameth-new-server/src/interfaces/session.interface'
import { updateSessionAction } from '@/lib/actions/sessions'

const UploadVideoForm = () => {
const UploadVideoForm = ({
session,
progress,
}: {
session: ISession
progress: number
}) => {
const [isLoading, setIsLoading] = useState(false)
const [cookie, setCookie] = useState(false)
const { address } = useAccount()
Expand All @@ -50,49 +59,58 @@ const UploadVideoForm = () => {
fetchCookie()
}, [])

async function onSubmit(values: z.infer<typeof videoUploadSchema>) {
const onSubmit = (values: z.infer<typeof videoUploadSchema>) => {
setIsLoading(true)
if (!address) {
toast.error('No wallet address found')
return
}

// TODO: Create and get session
const session = await fetchSession({
session: '65d382e3ad51d4af4f44758b',
updateSessionAction({
session: {
name: values.name,
description: values.description,
coverImage: values.coverImage,
_id: session._id!.toString(),
organizationId: session.organizationId,
eventId: session.eventId,
stageId: session.stageId,
start: session.start ?? Number(new Date()),
end: session.end ?? Number(new Date()),
speakers: session.speakers ?? [],
},
// TODO: How should I link a session to a video? Or should it create a new video?
})
const googleToken = await getCookie('google_token')
.then(async () => {
toast.success('Video created')
const googleToken = await getCookie('google_token')

// TODO: It should first be uploaded to Livepeer before uploading to YouTube
if (values.uploadYoutube === true && googleToken) {
const response = await fetch(
`${apiUrl()}/sessions/upload/${session?._id.toString()}?googleToken=${
googleToken.value
}`
)
if (!response.ok) {
throw new Error(`Something went wrong ${response.status}`)
}
console.log('All good')
}

// TODO: How should I link a session to a video? Or should it create a new video?
// updateSession({ session: {...session, name: values.name }, authToken: '' })
// .then(() => {
// toast.success('Video created')
// })
// .catch(() => {
// toast.error('Error uploading a video')
// })
// .finally(() => {
// setIsLoading(false)
// })
// TODO: It should first be uploaded to Livepeer before uploading to YouTube
if (values.uploadYoutube === true && googleToken) {
const response = await fetch(
`${apiUrl()}/sessions/upload/${session._id!.toString()}?googleToken=${
googleToken.value
}`
)
if (!response.ok) {
throw new Error(`Something went wrong ${response.status}`)
}
console.log('All good')
}
})
.catch(() => {
toast.error('Error uploading a video')
})
.finally(() => {
setIsLoading(false)
})
}

const isSubmitDisabled =
form.formState.isSubmitting ||
!form.formState.isValid ||
Object.keys(form.formState.dirtyFields).length === 0
Object.keys(form.formState.dirtyFields).length === 0 ||
progress < 100

return (
<Card className="p-4 bg-gray-200">
Expand Down
2 changes: 1 addition & 1 deletion packages/app/lib/actions/livepeer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const getAssetAction = async (assetId: string) => {
return null
}

return asset.asset?.status?.progress
return asset.asset?.status?.phase.toString()
} catch (e) {
console.error('Error fetching asset: ', assetId)
return null
Expand Down

0 comments on commit 95ef4bf

Please sign in to comment.