Utilizing Nextjs version 13 for implementing an API route with the ytdl-core

Recently, I've been experimenting with setting up a basic YouTube downloader using ytdl-core & nextjs.

In my code, there's an onClick function that makes an API call.

const onClick = async () => {
    await fetch("/api")
      .then(async (res: any) => {
        const blob = res.blob();
        console.log("resBlob", blob);
        return blob;
      })
      .then((blob: any) => console.log("BLOB", blob));
  };
export async function GET(request: Request) {
  const url =
    "https://www.youtube.com/watch?v=r_LroCsdB20&ab_channel=riserecords";
  const res = await ytdl(url)
    .pipe(fs.createWriteStream("video.mp4"))
    .on("finish", function () {
      console.log("FINISHED");
    });

  return new Response(res);
}

It seems like the response is being sent back immediately, even before the socket completes. I have noticed that if I move the response return inside the .on("finish"... block, it throws a headers error. When the onClick handler runs, it first logs a promise under "resBlob", and then it logs a blob with size: 15, type: "text/plain". I'm a bit stuck on where to go from here.

I've attempted to return the response within the on.("finish"... event. My goal is to send a response to the frontend and use that response to initiate the video download.

Answer №1

Ensure that you set the Headers prior to sending the response back. Keep in mind that sometimes the name may not be encoded correctly, requiring a modification for proper file download.

Here is a complete functioning example:

import ytdl from "ytdl-core";
import { NextResponse } from "next/server";

export async function GET(request: Request, response: Response) {
  const { searchParams } = new URL(request.url);
  const url = searchParams.get("link");
  const responseHeaders = new Headers(response.headers);

  if (!url) {
    return NextResponse.json({ data: "No URL" });
  }

  const randomName = Math.random().toString(36).substring(2, 15);

  responseHeaders.set(
    "Content-Disposition",
    `attachment; filename="${randomName}.mp4"`,
  );

  responseHeaders.set(
    "User-Agent",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
  );

  const data = ytdl(url);

  return new Response(data as any, {
    headers: responseHeaders,
  });
}

There is no need to use await; the process will automatically wait until the data has been retrieved.

Enjoy.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is preventing the selected values of a dropdown element from being set?

Although it may seem simple to assign values to select elements, I'm puzzled as to why the code below is setting the values to null instead of the correct ones for "form-type" and "genre". All other fields are being set correctly. It's worth not ...

Facing issues with ng-options duplication?

I have provided the code below that I would like to display: $scope.states="India"; $scope.cities="Madhya Pradesh"; $scope.city="Ajmer"; When attempting to implement this in a cascading dropdown format, I encountered an error. You can find my jsfidd ...

Can you provide guidance on achieving a gradient effect throughout the mesh, similar to the one shown in the example?

Check out my code snippet on JSFiddle: https://jsfiddle.net/gentleman_goat66/o5wn3bpf/215/ https://i.sstatic.net/r8Vxh.png I'm trying to achieve the appearance of the red/green box with the border style of the purple box. The purple box was created ...

Unable to view the HTML division

I am struggling with my website creation as I encounter issues with the .Main div. Despite setting background-color: orange; in the CSS, the color is not visible on the page. The inspector shows that it is positioned at 1440 x 0. Any assistance would be gr ...

Is the term 'Literal' in Javascript Arrays simply referring to its dynamic nature, allowing it to be modified at any time?

I'm confused why Mozilla refers to this as an Array 'Literal' when it's declared using the VARIABLE keyword and its content can be modified... var drinks = ["Espresso", "Latte", "Cappuccino"]; Could someone shed some light on this for ...

What is the process for transferring a file's contents to my server?

I am currently working on allowing users to import an OPML file that I parse server-side in my Rails application. However, I am facing difficulties as it appears that my server is not receiving the information correctly (neither the success nor error funct ...

What is the best way to set one property to be the same as another in Angular?

In my project, I have defined a class called MyClass which I later utilize in an Angular component. export class MyClass { prop: string; constructor(val){ this.prop = val; } public getLength(str: string): number { return str.length; } ...

Using JQuery to create animations with fadeIn and fadeOut effects is a great way to

As a complete newbie taking my first steps in front-end development, I spent most of my day trying to work out an animation function but couldn't quite get it right. Below are the snippets of HTML, CSS, and JavaScript codes: <!DOCTYPE html> < ...

Having trouble executing "npm install" following the clone from GitHub in React

After cloning a repository from GitHub, I attempted to run "npm install" but encountered the following error: https://i.sstatic.net/QM4RZ.png Since the project is still in development, should I install or add anything else to successfully run it? ...

Do developers only need type definitions for npm packages on their local machines?

It is my understanding that type definition modules for npm packages offer developers intellisense, eliminating the need to guess parameter types when using library methods. These modules have proven to be extremely valuable in my typescript project, esp ...

The background failed to display (potentially due to a hovering function)

I encountered an issue with a div that has a background image. Upon loading the page, the background image fails to display initially. However, when I hover over the div and then move my mouse elsewhere (due to a specific function described below), the bac ...

Updating the request body in Next 13 with middleware.ts: A step-by-step guide

I am looking for a way to modify the request body in NEXT 13 using a middleware function: import { NextRequest, NextResponse } from 'next/server'; enum MiddlewareRoutes { ACCESS = '/api/access', } const middlewareHandler = async ( ...

What are the different ways to switch between options in npx create-react-app?

I am currently in the process of building a fresh NextJs app. I have utilized the npm create-react-app command, and upon completion, the console is displaying Yes/No options with each question having either Yes or No highlighted. Is there a method to swit ...

Handling AJAX requests using jQuery

I'm currently in the process of learning how to utilize jQuery Ajax. Could you explain to me the significance of function(response), as well as what exactly is meant by response == 1 and response == 2? jQuery.post(ajaxurl, data, function(response) { ...

How can I remove a quadratic curved arrow tool in Fabric JS canvas after it has been created?

I'm currently working on developing a tool for creating quadratic curved arrows. For reference, I utilized a demo from the following link to build the tool: I have successfully created the tool as per my requirements. However, I am encountering some ...

What steps can I take to convert my React class into a function in order to incorporate Material UI components effectively?

With Emailjs set up successfully, my next step is integrating Material UI text fields (link: https://material-ui.com/components/text-fields/#text-field) to enhance the design of my project. The challenge I'm facing is incorporating Material UI classe ...

Activating Jquery toggle on several elements instead of just the specified element

Hey everyone, I have a question regarding jQuery. I have a toggle function that is supposed to activate when clicking on a specific element - in this case, my logo image with the id of #logobutton. The toggle works great, but there's a problem. The an ...

Restricting concurrent asynchronous $http get requests in Angular程序

I've set up a page displaying a table of IP addresses connecting to a media stream. I've linked them to a database that includes location information and have managed to serve duplicate IP requests from cache to lighten the load. However, the pag ...

What steps do I need to take to convert a view from a three.js camera and scene to a bcf cameraview?

I am attempting to convert a ifc.js viewer file into a bcf format. The ifc.js viewer utilizes a three.js webglrenderer along with a camera and scene setup. Shown below is an example: https://i.sstatic.net/oTphJ.png https://i.sstatic.net/8Dtag.png I would ...

Incorrect rendering of the <li> tag

I've been working on creating a simple web "to do list" but I've encountered an issue. When I manually add todos and click on them, the 'text-decoration: line-through;' property is ignored, and I can't see the strikethrough effect ...