This commit is contained in:
ForeverPyrite
2024-09-27 21:55:22 -04:00
parent 6fefd65f86
commit e66a16ed9a
12 changed files with 225 additions and 26 deletions

25
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,25 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Flask",
"type": "debugpy",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "app.py",
"FLASK_DEBUG": "1"
},
"args": [
"run",
"--debug",
"--no-reload"
],
"jinja": true,
"autoStartBrowser": false
}
]
}

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"html.autoClosingTags": true,
"html.format.enable": true,
"html.autoCreateQuotes": true
}

31
app.py Normal file
View File

@@ -0,0 +1,31 @@
from flask import Flask, render_template, request
from main import get_auto_transcript, get_video_id, create_and_stream
app = Flask(__name__, static_folder="website/static", template_folder="website")
@app.route('/')
def home():
return render_template('index.html')
@app.route('/process_url', methods=['POST'])
def process_url():
url = request.form['url']
# Extract the video ID from the URL
video_id = get_video_id(url) # Modify this function to accept the URL
if not video_id:
return "Couldn't parse video ID from URL. (Are you sure you entered a valid YouTube.com or YouTu.be URL?)"
# Get the transcript for that video ID
transcript = get_auto_transcript(video_id)
if (not transcript):
return "Successfully parsed video ID from URL, however the ID was either invalid, the transcript was disabled by the video owner, or some other error was raised because of YouTube."
# Process the transcript and stream the result.
stream = create_and_stream(transcript)
# Return a response
return stream # Add more detailed output if needed
if __name__ == '__main__': # Change this line to properly check for main
app.run(debug=True)

46
main.py
View File

@@ -3,6 +3,7 @@
import re
# Youtube Transcript stuff import
import youtube_transcript_api._errors
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api.formatters import TextFormatter
@@ -41,6 +42,7 @@ class EventHandler(AssistantEventHandler):
if output.type == "logs":
print(f"\n{output.logs}", flush=True)
# Setting up OpenAI Client with API Key
api_key =os.getenv("OPENAI_API_KEY")
client = OpenAI(
@@ -65,44 +67,42 @@ def create_and_stream(transcript):
event_handler=EventHandler()
) as stream:
stream.until_done()
return
messages = stream.get_final_messages()
return messages[0].content[0].text.value
def get_video_id():
# local consts
def get_video_id(url):
youtu_be = r'(?<=youtu.be/)([A-Za-z0-9_-]{11})'
youtube_com = r'(?<=youtube\.com\/watch\?v=)([A-Za-z0-9_-]{11})'
# local vars
valid_id = False
# Get URL from user
while(not valid_id):
user_url = input("Enter the URL of the YouTube video: ")
id = re.search(youtu_be, user_url)
id = re.search(youtu_be, url)
if not id:
id = re.search(youtube_com, url)
if (not id):
id = re.search(youtube_com, user_url)
if not id:
print("Couldn't parse video ID from URL")
return None
if (not id):
print("Error: Couldn't parse video ID from URL, please make sure you are pasting a full \"youtube.com\" or \"youtu.be url\"\n")
else:
valid_id = True
id = id.group(1)
print(id)
return id
return id.group(1)
# Takes the transcript and formats it in basic text before writing it to auto-transcript.txt
def get_auto_transcript(video_id):
transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['en'], proxies=None, cookies=None, preserve_formatting=False)
formatter = TextFormatter
trans_api_errors = youtube_transcript_api._errors
try:
transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['en'], proxies=None, cookies=None, preserve_formatting=False)
except trans_api_errors.TranscriptsDisabled:
return None
txt_transcript = formatter.format_transcript(self=any, transcript=transcript)
print(txt_transcript)
formatter = TextFormatter() # Ensure that you create an instance of TextFormatter
txt_transcript = formatter.format_transcript(transcript)
return txt_transcript
# Stores the video id imputted by the user
"""
video_id = get_video_id()
transcript = get_auto_transcript(video_id)
create_and_stream(transcript)
"""

BIN
requirements.txt Normal file

Binary file not shown.

View File

30
website/index.html Normal file
View File

@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Screw You Bardo</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="icon" type="image/x-icon" href="https://www.foreverpyrite.com/favicon.ico">
<script src="{{ url_for('static', filename='script.js')}}"></script>
</head>
<body>
<div class="content">
<p id="response-area">Response will appear here.</p>
<div class="form_box">
<input id="url_box" placeholder="Paste the lecture URL here." autofocus></input>
<input id="submit" type="submit" onclick=""></input>
</div>
</div>
</body>
</html>

Binary file not shown.

Binary file not shown.

31
website/static/script.js Normal file
View File

@@ -0,0 +1,31 @@
document.addEventListener("DOMContentLoaded", (event) => {
document.getElementById('submit').addEventListener('click', function() {
var url = document.getElementById('url_box').value;
const response_area = document.getElementById('response-area');
if (!url) {
response_area.innerText = 'Please enter a URL.';
return;
}
else{
response_area.innerText = "Sending URL and retriving transcript."
}
fetch('/process_url', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ url: url })
})
.then(response => response.text())
.then(data => {
response_area.innerText = data;
})
.catch(error => {
console.error('Error:', error);
response_area.innerText = 'An error occurred. Please try again.';
});
});
});

View File

@@ -0,0 +1,77 @@
@font-face {
font-family: 'nimbus_sans_d_otlight';
src: url('font-files/nimbus-sans-d-ot-light.woff2') format('woff2'),
url('font-files/nimbus-sans-d-ot-light.woff') format('woff');
font-weight: normal;
font-style: normal;
}
* {
font-family: 'nimbus_sans_d_otlight';
color: white;
}
body {
display: flex;
flex-direction: column;
width: 100%;
max-width: 100vw;
height: 100%;
min-height: 100vh;
max-height: 100vh;
margin: 0;
background-color: rgb(31, 31, 31);
}
body .content {
display: flex;
flex-direction: column;
align-self: center;
width: 75%;
max-width: 65vw;
height: 100%;
min-height: 100vh;
max-height: 100vh;
}
#response-area {
display: block;
height: 90%;
min-height: 90vh;
overflow: auto;
flex-wrap: wrap;
align-content: flex-end;
}
.form_box {
display: flex;
width: 100%;
justify-content: space-between;
align-content: space-around;
}
#url_box {
display: flex;
height: 5%;
min-height: 5vh;
width: 90%;
min-width: 80vh;
background-color: rgb(31, 31, 31);
}
#submit {
display: flex;
width: 5%;
min-width: 3vw;
background-color: rgb(49, 49, 49);
}
#submit:hover {
cursor: pointer;
background-color: rgb(31, 31, 31);
}
input {
border-radius: 15px;
}