-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
podcast controller, audio summarizer
- Loading branch information
Showing
13 changed files
with
550 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,34 @@ | ||
class PodcastsController < ApplicationController | ||
|
||
|
||
def show | ||
@user = User.find_by(username: params[:user_id]) | ||
end | ||
|
||
def edit | ||
@user = User.find_by(username: params[:user_id]) | ||
@info = @user.podcaster_info || @user.build_podcaster_info | ||
end | ||
|
||
def update | ||
@user = User.find_by(username: params[:user_id]) | ||
@info = @user.podcaster_info || @user.build_podcaster_info | ||
@info.update(podcaster_params) | ||
redirect_to user_podcast_path(@user.username) | ||
end | ||
|
||
|
||
def create | ||
@user = User.find_by(username: params[:user_id]) | ||
@info = @user.podcaster_info || @user.build_podcaster_info | ||
@info.update(podcaster_params) | ||
redirect_to user_podcast_path(@user.username) | ||
end | ||
|
||
|
||
private | ||
|
||
def podcaster_params | ||
params.require(:podcaster_info).permit(:about, :title, :description) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# app/services/audio_summarizer.rb | ||
require 'openai' | ||
require 'securerandom' | ||
require 'tmpdir' | ||
|
||
class AudioSummarizer | ||
MAX_FILE_SIZE_MB = 20 | ||
MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024 | ||
|
||
def initialize(file_path) | ||
@file_path = file_path | ||
@client = OpenAI::Client.new(access_token: ENV["OPENAI_API_KEY"], log_errors: true) | ||
end | ||
|
||
def summarize | ||
chunk_paths = split_audio_by_silence | ||
transcriptions = chunk_paths.map { |chunk_path| | ||
Rails.logger.info("CHUNK PATH #{chunk_path}") | ||
transcribe_chunk(chunk_path) | ||
} | ||
text = transcriptions.join("\n") | ||
sumarize_transcription(text) | ||
ensure | ||
cleanup_temp_files(chunk_paths) | ||
end | ||
|
||
def sumarize_transcription(text) | ||
response = @client.chat( | ||
parameters: { | ||
model: "gpt-4o", | ||
messages: [ | ||
{ role: "assistant", content: "summarize the podcast transcription for the Rauversion platform"}, | ||
{ role: "user", content: text} | ||
], | ||
temperature: 0.7, | ||
}) | ||
response.dig("choices", 0, "message", "content") | ||
end | ||
|
||
private | ||
|
||
def split_audio_by_silence | ||
output_dir = Dir.mktmpdir | ||
chunk_pattern = File.join(output_dir, 'chunk_%03d.wav') | ||
|
||
# Split the file by silence detection | ||
`ffmpeg -i "#{@file_path}" -af silencedetect=noise=-30dB:d=0.5 -f segment -segment_time 30 -c:a pcm_s16le "#{chunk_pattern}"` | ||
|
||
chunk_paths = Dir.glob("#{output_dir}/chunk_*.wav") | ||
valid_chunks = [] | ||
|
||
chunk_paths.each do |chunk_path| | ||
if File.size(chunk_path) > MAX_FILE_SIZE_BYTES | ||
# Re-split large chunks further | ||
valid_chunks += split_large_chunk(chunk_path, output_dir) | ||
File.delete(chunk_path) # Delete the original large chunk | ||
else | ||
valid_chunks << chunk_path | ||
end | ||
end | ||
|
||
valid_chunks | ||
end | ||
|
||
def split_large_chunk(chunk_path, output_dir) | ||
temp_pattern = File.join(output_dir, 'temp_chunk_%03d.wav') | ||
|
||
`ffmpeg -i "#{chunk_path}" -f segment -segment_time 15 -c:a pcm_s16le "#{temp_pattern}"` | ||
|
||
Dir.glob("#{output_dir}/temp_chunk_*.wav").select do |path| | ||
File.size(path) <= MAX_FILE_SIZE_BYTES | ||
end | ||
end | ||
|
||
def transcribe_chunk(chunk_path) | ||
response = @client.audio.transcribe( | ||
parameters: { | ||
file: File.open(chunk_path), | ||
model: "whisper-1" | ||
} | ||
) | ||
response['text'] | ||
end | ||
|
||
def cleanup_temp_files(files) | ||
files.each { |file| File.delete(file) if File.exist?(file) } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<<footer class="border-t border-subtle bg-default py-10 pb-40 sm:py-16 sm:pb-32 lg:hidden"> | ||
<div class="mx-auto px-4 sm:px-6 md:max-w-2xl md:px-4"> | ||
<section> | ||
<h2 class="flex items-center font-mono text-sm font-medium leading-7 text-default"> | ||
<svg aria-hidden="true" viewBox="0 0 10 10" class="h-2.5 w-2.5"> | ||
<path d="M0 5a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V5Z" class="fill-violet-300"></path> | ||
<path d="M6 1a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V1Z" class="fill-pink-300"></path> | ||
</svg> | ||
<span class="ml-2.5">About</span> | ||
</h2> | ||
<p class="mt-2 text-base leading-7 text-subtle lg:line-clamp-4">In this show, Eric and Wes dig deep to get to the facts with guests who have been labeled villains by a society quick to judge, without actually getting the full story. Tune in every Thursday to get to the truth with another misunderstood outcast as they share the missing context in their tragic tale.</p> | ||
<button type="button" class="mt-2 hidden text-sm font-bold leading-6 text-pink-500 hover:text-pink-700 active:text-pink-900 lg:inline-block">Show more</button> | ||
</section> | ||
<h2 class="mt-8 flex items-center font-mono text-sm font-medium leading-7 text-default"> | ||
<svg aria-hidden="true" viewBox="0 0 11 12" class="h-3 w-auto fill-slate-300"> | ||
<path d="M5.019 5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Zm3.29 7c1.175 0 2.12-1.046 1.567-2.083A5.5 5.5 0 0 0 5.019 7 5.5 5.5 0 0 0 .162 9.917C-.39 10.954.554 12 1.73 12h6.578Z"></path> | ||
</svg> | ||
<span class="ml-2.5">Hosted by</span> | ||
</h2> | ||
<div class="mt-2 flex gap-6 text-sm font-bold leading-7 text-default">Eric Gordon <span aria-hidden="true" class="text-slate-400">/</span>Wes Mantooth </div> | ||
</div> | ||
</footer>> |
Oops, something went wrong.