Skip to content

Commit

Permalink
Merge pull request #4 from yoanbernabeu/translation
Browse files Browse the repository at this point in the history
Add Translate command (with DeepL free Account)
  • Loading branch information
yoanbernabeu authored Jun 17, 2023
2 parents f750c42 + 20fb4ed commit aae062f
Show file tree
Hide file tree
Showing 3 changed files with 252 additions and 3 deletions.
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ This tool leverages artificial intelligence to efficiently transcribe speech in

It's designed to improve the accessibility and convenience of video content, ensuring that no matter your language or hearing ability, you can fully engage with and comprehend the material.

## Usage - The simplest way
## Features

### Generate subtitles - The simplest way

The simplest way to use Subtitlr without configuration is to use the following command:

```bash
Subtitlr generate --id qJpR1NBx4cU --lang fr --output output.srt --apiKey sk-****************************
```

## Usage - With configuration
### Generate subtitles - With configuration

You can also use a `.env` file to store your API key (in `OPENAI_API_KEY` variable) and use the following command:

Expand All @@ -37,6 +39,20 @@ And after that, you can use the following command without the `--apiKey` paramet
Subtitlr generate --id qJpR1NBx4cU --lang fr --output output.srt
```

### Translating subtitles

> For translations we offer you the possibility to use the DeepL API with a free account only (500000 per month).
>
> Create an *free* account on [DeepL](https://www.deepl.com/fr/signup?cta=free-login-signup/)
You must have previously generated your subtitle file with the `generate` command.

You can use the following command to translate subtitles:

```bash
Subtitlr translate --input input.srt --lang EN --output output_EN.srt --apiKeyDeepl ****************************
```

## Requirements

* [OpenAI API key](https://beta.openai.com/)
Expand All @@ -46,13 +62,24 @@ Subtitlr generate --id qJpR1NBx4cU --lang fr --output output.srt

## Parameters

### `generate` command

| Name | Description | Required |
| --- | --- | --- |
| id | Youtube video id | true |
| lang | Language speaking in the video (in ISO 639-1 format) | true |
| output | Output file | true |
| apiKey | OpenAI API key | false (if you use the `configure` command) |

### `translate` command

| Name | Description | Required |
| --- | --- | --- |
| input | Input file | true |
| lang | Language to translate (in ISO 639-1 format) | true |
| output | Output file | true |
| apiKeyDeepl | DeepL API key | true |

## Installation

### From binary
Expand Down
222 changes: 222 additions & 0 deletions cmd/translate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
"os"

"github.com/spf13/cobra"
)

// translateCmd represents the translate command
var translateCmd = &cobra.Command{
Use: "translate",
Short: "Translate the subtitles in SRT format with DeepL",
Long: `The 'translate' command is a crucial feature of our subtitle generator application. Once activated, this command initiates the process of translating subtitles from a provided SRT file`,
Run: func(cmd *cobra.Command, args []string) {
/* Variables declaration */
input, _ := cmd.Flags().GetString("input")
lang, _ := cmd.Flags().GetString("lang")
output, _ := cmd.Flags().GetString("output")
apiKeyDeepL, _ := cmd.Flags().GetString("apiKeyDeepL")

/* Displaying the values of the flags */
fmt.Println("---------------------------------------")
fmt.Println("You have entered the following values:")
fmt.Println("input:", input)
fmt.Println("lang:", lang)
fmt.Println("output:", output)
fmt.Println("apiKeyDeepL:", apiKeyDeepL)
fmt.Println("---------------------------------------")

/* Uploading the file to DeepL */
deepLResponse := uploadFile(input, lang, apiKeyDeepL)

/* Checking the status of the translation */
fmt.Println("=======================================")

for {
checkStatusResponse := checkStatus(deepLResponse, apiKeyDeepL)
if checkStatusResponse.Status == "done" {
downloadFile(deepLResponse, output, apiKeyDeepL)
break
}
}

},
}

type DeepLResponse struct {
DocumentID string `json:"document_id"`
DocumentKey string `json:"document_key"`
}

type DeepLCheckStatusResponse struct {
DocumentID string `json:"document_id"`
Status string `json:"status"`
SecondsRemaining int `json:"seconds_remaining"`
}

func init() {
rootCmd.AddCommand(translateCmd)

translateCmd.Flags().String("input", "", "Input file")
translateCmd.Flags().String("lang", "", "Language (in ISO 639-1 format) to translate the subtitles to")
translateCmd.Flags().String("output", "", "Output file")
translateCmd.Flags().String("apiKeyDeepL", "", "DeepL API key")

translateCmd.MarkFlagRequired("input")
translateCmd.MarkFlagRequired("lang")
translateCmd.MarkFlagRequired("output")
translateCmd.MarkFlagRequired("apiKeyDeepL")
}

func uploadFile(input string, lang string, apiKeyDeepL string) DeepLResponse {
fmt.Println("=======================================")
fmt.Println("Uploading the file to DeepL...")

// Create a buffer to store our request body as bytes
var b bytes.Buffer
w := multipart.NewWriter(&b)

// Open the file
f, err := os.Open(input)
if err != nil {
log.Fatal(err)
}
defer f.Close()

// Add the file to the request body
fw, err := w.CreateFormFile("file", f.Name()+".txt")
if err != nil {
log.Fatal(err)
}
if _, err = io.Copy(fw, f); err != nil {
log.Fatal(err)
}

// Add our fields to the multipart writer
if err = w.WriteField("target_lang", lang); err != nil {
log.Fatal(err)
}

// Close the multipart writer
if err = w.Close(); err != nil {
log.Fatal(err)
}

// Create a new request
req, _ := http.NewRequest("POST", "https://api-free.deepl.com/v2/document", &b)

// Set the content type header, as well as the boundary we're going to use
req.Header.Set("Content-Type", w.FormDataContentType())

// Set the authorization header (Authorization: DeepL-Auth-Key [yourAuthKey])
req.Header.Set("Authorization", "DeepL-Auth-Key "+apiKeyDeepL)

// Set the user agent header (User-Agent: YourApp/1.2.3)
req.Header.Set("User-Agent", "Subtitlr")

// Send the request
client := &http.Client{}
resp, _ := client.Do(req)

// Read the response body
buf := new(bytes.Buffer)
_, _ = buf.ReadFrom(resp.Body)

// Close the response body
_ = resp.Body.Close()

// Parse the response body into a DeepLResponse struct
var deepLResponse DeepLResponse
json.Unmarshal(buf.Bytes(), &deepLResponse)

// Display the document ID and document key
fmt.Println("DeepL response:")
fmt.Println("Document ID:", deepLResponse.DocumentID)
fmt.Println("Document Key:", deepLResponse.DocumentKey)
fmt.Println("=======================================")

return deepLResponse
}

func checkStatus(deepLResponse DeepLResponse, apiKeyDeepL string) DeepLCheckStatusResponse {
// Create a new request
req, _ := http.NewRequest("POST", "https://api-free.deepl.com/v2/document/"+deepLResponse.DocumentID, nil)
req.Header.Set("Authorization", "DeepL-Auth-Key "+apiKeyDeepL)
req.Header.Set("User-Agent", "Subtitlr")

// Add the document key to the request body
q := req.URL.Query()
q.Add("document_key", deepLResponse.DocumentKey)
req.URL.RawQuery = q.Encode()

// Send the request
client := &http.Client{}
resp, _ := client.Do(req)

// Read the response body
buf := new(bytes.Buffer)
_, _ = buf.ReadFrom(resp.Body)

// Close the response body
_ = resp.Body.Close()

// Parse the response body into a DeepLCheckStatusResponse struct
var deepLCheckStatusResponse DeepLCheckStatusResponse
json.Unmarshal(buf.Bytes(), &deepLCheckStatusResponse)

fmt.Println("Seconds remaining:", deepLCheckStatusResponse.SecondsRemaining)

return deepLCheckStatusResponse
}

func downloadFile(deepLResponse DeepLResponse, output string, apiKeyDeepL string) {
fmt.Println("=======================================")
fmt.Println("Downloading the translated file...")
fmt.Println("Document ID:", deepLResponse.DocumentID)
fmt.Println("Document Key:", deepLResponse.DocumentKey)

// Create a new request
req, _ := http.NewRequest("POST", "https://api-free.deepl.com/v2/document/"+deepLResponse.DocumentID+"/result", nil)
req.Header.Set("Authorization", "DeepL-Auth-Key "+apiKeyDeepL)
req.Header.Set("User-Agent", "Subtitlr")

// Add the document key to the request body
q := req.URL.Query()
q.Add("document_key", deepLResponse.DocumentKey)
req.URL.RawQuery = q.Encode()

// Send the request
client := &http.Client{}
resp, _ := client.Do(req)

// Read the response body
buf := new(bytes.Buffer)
_, _ = buf.ReadFrom(resp.Body)

// Close the response body
_ = resp.Body.Close()

// Write the response body to the output file
err := ioutil.WriteFile(output, buf.Bytes(), 0644)
if err != nil {
log.Fatal(err)
}

// Display the status of the translation
fmt.Println("DeepL response:")
fmt.Println("File downloaded successfully!")
fmt.Println("=======================================")
}
2 changes: 1 addition & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ echo "Distribution: $distro"
echo "Architecture: $arch"

# Subtitlr version
version="0.1.1"
version="0.2.0"

echo "Version: $version"
echo "------------------------"
Expand Down

0 comments on commit aae062f

Please sign in to comment.