From d685c1c71aa757b44445d139b0b84f8631da9722 Mon Sep 17 00:00:00 2001 From: Arkaprabha Chakraborty Date: Thu, 8 Aug 2024 03:06:17 +0530 Subject: [PATCH] Add a README --- README.md | 90 ++++++++++++++++++++++++++++++++++++++++++++++ blob/downlink.png | Bin 0 -> 25072 bytes 2 files changed, 90 insertions(+) create mode 100644 README.md create mode 100644 blob/downlink.png diff --git a/README.md b/README.md new file mode 100644 index 0000000..9c21c5c --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +![downlink.png](blob/downlink.png) + +# DownLink + +DownLink is a web application that allows users to download YouTube videos from URLs using a simple interface. This repository contains the code for both the frontend and backend of the application. + +## Table of Contents + +- [Features](#features) +- [Technologies](#technologies) +- [Setup](#setup) + - [Prerequisites](#prerequisites) + - [Installation](#installation) +- [Usage](#usage) +- [API Endpoints](#api-endpoints) +- [Contributing](#contributing) +- [License](#license) + +## Features + +- Download YouTube videos from a provided URL. +- Choose video quality (480p, 720p, 1080p) before downloading. +- Responsive UI built with React and Tailwind CSS. +- Backend API built with Go and the Echo framework. +- Utilizes yt-dlp for downloading and ffmpeg for converting files. + +## Technologies + +- **Frontend**: React, Axios, Tailwind CSS +- **Backend**: Go, Echo, yt-dlp, ffmpeg +- **Containerization**: Docker, Docker Compose + +## Setup + +### Prerequisites + +- Docker +- Docker Compose +- Node.js and npm (for frontend development) +- Python 3 (for `yt-dlp` and `ffmpeg`) + +### Installation + +1. **Clone the repository:** + + ```bash + git clone https://github.com/arkorty/downlink.git + cd downlink + ``` + +2. **Set up environment variables:** + + Create a `.env` file in the root of the frontend directory and add the following: + + ```env + REACT_APP_BACKEND_URL=http://localhost:8080 + ``` + +3. **Run the application using Docker Compose:** + + ```bash + docker-compose up --build + ``` + + This command will build and start the Docker containers for the frontend and backend. + +4. **Access the application:** + + Open your browser and navigate to `http://localhost:3000` to access the frontend. The backend API will be available at `http://localhost:8080`. + +## Usage + +### Downloading a Video + +1. Enter the video URL and select the desired quality in the form on the homepage. +2. Click the "Download" button. +3. The video will be processed and downloaded to your device. + +## API Endpoints + +- **GET `/downlink/`**: Check if the backend is running. +- **POST `/downlink/download`**: Submit a request to download and merge video and audio. Requires JSON body with `url` and `quality` fields. + +## Contributing + +We welcome contributions to DownLink! If you have suggestions, bug fixes, or new features, feel free to open an issue or submit a pull request. Thank you for helping improve DownLink! + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/blob/downlink.png b/blob/downlink.png new file mode 100644 index 0000000000000000000000000000000000000000..c099bef3e78a64c850f9e83b24192d5ddcb5901a GIT binary patch literal 25072 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 NDXAPwJ#zWx{|63u!>RxP literal 0 HcmV?d00001