Help
RSS
API
Feed
Maltego
Contact
Domain > audition.c8c.ai
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2025-07-11
3.170.103.33
(
ClassC
)
2026-02-05
3.163.24.13
(
ClassC
)
Port 80
HTTP/1.1 301 Moved PermanentlyServer: CloudFrontDate: Thu, 05 Feb 2026 17:09:34 GMTContent-Type: text/htmlContent-Length: 167Connection: keep-aliveLocation: https://audition.c8c.ai/X-Cache: Redirect from cloudfrontVia: 1.1 f36cc119cb86b2f70c315ca53fd1b4ee.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P2X-Amz-Cf-Id: WeGnMTwz2Ioqcf-LZcdSSQVQtMuHH_wiEuNJX8tf-4LwwYHofZcq5Q html>head>title>301 Moved Permanently/title>/head>body>center>h1>301 Moved Permanently/h1>/center>hr>center>CloudFront/center>/body>/html>
Port 443
HTTP/1.1 200 OKContent-Type: text/htmlContent-Length: 104303Connection: keep-aliveDate: Thu, 05 Feb 2026 17:09:35 GMTLast-Modified: Thu, 28 Aug 2025 13:29:52 GMTETag: 33531a5a01576ae11c834d7bbc503d96x-amz-server-side-encryption: AES256x-amz-version-id: lkzYLFjR3G_RAhbi7r4P4fP3_yClgBcIAccept-Ranges: bytesServer: AmazonS3X-Cache: Miss from cloudfrontVia: 1.1 5b69cd230a06f482da15abd9c53bb694.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P2X-Amz-Cf-Id: sBjKDRZqSpVIcW8VX7BhpkAe7i6eiXAlmF_5whrXckLJw1L63vBBLA !DOCTYPE html>html langen>head> meta charsetUTF-8> meta nameviewport contentwidthdevice-width, initial-scale1.0> title>C8C Auditions - English (PRESIGNED SECURE)/title> link relicon hrefdata:image/svg+xml,svg xmlnshttp://www.w3.org/2000/svg viewBox0 0 100 100>text y.9em font-size90>π€/text>/svg>> !-- Google Analytics --> script async srchttps://www.googletagmanager.com/gtag/js?idG-S344GMCZBB>/script> script> window.dataLayer window.dataLayer || ; function gtag(){dataLayer.push(arguments);} gtag(js, new Date()); gtag(config, G-S344GMCZBB, { page_title: English Audition Portal, page_path: /english }); // Track form interactions document.addEventListener(DOMContentLoaded, function() { // Track when someone starts filling the form let formStarted false; const trackFormStart function() { if (!formStarted) { formStarted true; gtag(event, form_start, { event_category: engagement, event_label: english_portal, page_location: window.location.href }); } }; // Add listeners to form fields (will be attached after page loads) setTimeout(() > { firstName, lastName, email, phone, age, sex, location.forEach(fieldId > { const field document.getElementById(fieldId); if (field) { field.addEventListener(focus, trackFormStart, { once: true }); } }); }, 1000); }); /script> style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; background-color: #f5f5f5; } .container { background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .logo { text-align: center; margin-bottom: 30px; } .logo-circle { width: 120px; height: 120px; background: linear-gradient(135deg, #7B68EE, #6A5ACD); border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; margin-bottom: 20px; } .logo-text { color: white; font-size: 32px; font-weight: bold; font-family: Arial, sans-serif; } .form-group { margin-bottom: 20px; } label { display: block; margin-bottom: 5px; font-weight: bold; } input, select { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; } .intro-section { background: #e6f2ff; padding: 25px; border-radius: 8px; margin: 20px 0 30px 0; border-left: 4px solid #007bff; line-height: 1.6; } .intro-section h2 { color: #004085; margin-top: 0; margin-bottom: 15px; } .intro-section p { color: #004085; margin-bottom: 15px; } .intro-section p:last-child { margin-bottom: 0; } .instructions-section { background: #e8f5e8; padding: 20px; border-radius: 5px; margin: 20px 0; border-left: 4px solid #28a745; } .script-section { background: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0; } .script-text { font-weight: bold; margin-bottom: 20px; padding: 15px; background: white; border-radius: 5px; border: 1px solid #dee2e6; } .stage-direction { background: #f8f9fa; color: #666; font-style: italic; font-weight: normal; padding: 8px 12px; border-radius: 3px; margin: 5px 0; border-left: 3px solid #007bff; font-size: 14px; } .dialogue-line { background: #fff3cd; color: #856404; font-weight: bold; padding: 12px 15px; border-radius: 5px; margin: 8px 0; border-left: 4px solid #ffc107; font-size: 16px; line-height: 1.4; } .recording-controls { text-align: center; margin: 30px 0; padding: 20px; background: #f8f9fa; border-radius: 5px; } button { background: #007bff; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 16px; cursor: pointer; margin: 10px; } button:hover { background: #0056b3; } button:disabled { background: #6c757d; cursor: not-allowed; } #recordButton { background: #dc3545; font-size: 18px; padding: 20px 40px; } #recordButton.recording { background: #28a745; animation: pulse 1s infinite; } #readyButton { background: #28a745; font-size: 18px; padding: 20px 40px; } @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.7; } 100% { opacity: 1; } } .status { text-align: center; margin: 20px 0; padding: 15px; border-radius: 5px; font-weight: bold; } .status.success { background: #d4edda; color: #155724; } .status.error { background: #f8d7da; color: #721c24; } .status.info { background: #d1ecf1; color: #0c5460; } .audio-preview { text-align: center; margin: 20px 0; } audio { width: 100%; margin: 10px 0; } .name-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; } .hidden { display: none; } /* Thank You Page Styles */ #thankYouPage { text-align: center; padding: 40px 20px; } #thankYouPage h2 { color: #28a745; margin-bottom: 20px; } .feedback-section { background: #f8f9fa; padding: 30px; border-radius: 10px; margin: 30px 0; text-align: left; } /style>/head>body> div classcontainer> !-- Main Content --> div idmainContent> div classlogo> div classlogo-circle> div classlogo-text>c8c.ai/div> /div> h1>π Conversational Personas Casting/h1> p>Record your voice following specific character prompts and stage directions/p> /div> form idauditionForm> div classname-fields> div classform-group> label forfirstName>First Name */label> input typetext idfirstName required> /div> div classform-group> label forlastName>Last Name */label> input typetext idlastName required> /div> /div> div classform-group> label foremail>Email Address */label> input typeemail idemail required> /div> div classform-group> label forphone>Phone Number/label> input typetel idphone placeholdere.g., +1 555 123 4567> /div> div classform-group> label forage>Age */label> input typenumber idage min18 max99 required> /div> div classform-group> label forsex>Sex */label> select idsex required> option value>Select.../option> option valuemale>Male/option> option valuefemale>Female/option> /select> /div> div classform-group> label forlocation>Location */label> select idlocation required> option value>Select your location.../option> option valuenew-york>New York/option> option valuetampa>Tampa/option> /select> /div> /form> div classinstructions-section> h4>π Audition Instructions/h4> p>In this casting, you will record your voice on your phone or computer. You will read prompts, each one with a different expression and stage direction./p> h5>Make sure you:/h5> ul> li>Read fluently and expressively the sentences exactly as theyre given/li> li>Follow the stage direction and keep it during the whole sentence/li> li>Do not hesitate, stutter or pause while reading/li> li>Record in a quiet environment (no dogs, cars, AC, etc.)/li> li>Avoid making external noises (paper rustling, pen clicking, playing with your necklace, etc.) during recording/li> li>Do not try to change your voice or use unnatural tones/li> /ul> h5>Tips:/h5> ul> li>Review the script and practice before recording/li> li>There are different prompts to be read, assigned to fictional characters/li> li>Listen to your recording and re-record if it doesnt sound good/li> li>We want to hear a person talking, not someone reading the lines/li> /ul> /div> div styletext-align: center; margin: 40px 0;> h3 stylemargin-bottom: 30px; color: #333;>You can take your audition in two formats, choose the one thats better for you and you only need to audition once for this project ... Good Luck!/h3> div stylebackground: #f8f9fa; padding: 15px; border-radius: 5px; margin: 20px 0; border-left: 4px solid #007bff; font-size: 14px;> p>C8C is a wholly owned subsidiary of Focus Forward, LLC.br>By clicking one of the start recording sessions below, you agree to the a hrefhttps://www.focusfwd.com/terms-of-service/ target_blank stylecolor: #007bff; text-decoration: none;>Terms of Use/a>./p> /div> div styledisplay: grid; grid-template-columns: 1fr 1fr; gap: 30px; max-width: 800px; margin: 0 auto;> style> @media (max-width: 768px) { divstyle*grid-template-columns: 1fr 1fr { grid-template-columns: 1fr !important; gap: 20px !important; } } /style> !-- Continuous Recording Option --> div stylebackground: #f8f9fa; padding: 25px; border-radius: 10px; border: 2px solid #007bff;> h4 stylecolor: #007bff; margin-bottom: 15px;>π€ Record All at Once/h4> p stylemargin-bottom: 20px; color: #666; line-height: 1.4;> Record all 10 prompts in one continuous session. Read through the entire script from start to finish. /p> button typebutton onclickstartContinuousMode() stylebackground: #007bff; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 16px; width: 100%;> Start Continuous Recording /button> /div> !-- Line by Line Recording Option --> div stylebackground: #f8f9fa; padding: 25px; border-radius: 10px; border: 2px solid #28a745;> h4 stylecolor: #28a745; margin-bottom: 15px;>π Record Line by Line/h4> p stylemargin-bottom: 20px; color: #666; line-height: 1.4;> Record each of the 10 prompts individually. Perfect each line separately, then combine them automatically. /p> button typebutton onclickstartLineByLineRecording() stylebackground: #28a745; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 16px; width: 100%;> Start Line-by-Line Recording /button> /div> /div> /div> !-- Recording Controls at Top --> div classrecording-controls idrecordingControlsTop styledisplay: none;> h3>π€ Recording Controls - Top/h3> p>Click Start Recording and read all the prompts below./p> button typebutton idrecordButton onclicktoggleRecording() disabled> π€ Start Recording /button> button typebutton idpauseButton onclickpauseRecording() disabled stylebackground: #ffc107;> βΈοΈ Pause /button> button typebutton idresetButton onclickresetRecording() disabled> π Reset Recording /button> /div> !-- Script Content (shown only after ready button) --> div idscriptContent classscript-section styledisplay: none;> h3>π The Script - All Prompts/h3> p>strong>Record all prompts below, following each stage direction./strong>/p> div classscript-text> strong>Prompt 1:/strong> div classstage-direction> Stage directions: Romantic Book Reader You are reading a book during a library storytime event. Speak with a lively, enthusiastic tone, using a slightly faster pace and dynamic prosody /div> div classdialogue-line> Hello everyone! Today, Im thrilled to share my thoughts on The Notebook by Nicholas Sparks. This book is an absolute gem, filled with love, passion, and unforgettable moments. /div> /div> div classscript-text> strong>Prompt 2:/strong> div classstage-direction> Stage directions: maintain a fast pace with dynamic prosody /div> div classdialogue-line> From the very first page, youre drawn into the story of Noah and Allie, two young lovers whose romance is as intense as it is beautiful. Their love story is one for the ages! /div> /div> div classscript-text> strong>Prompt 3:/strong> div classstage-direction> Stage directions: Fitness Trainer You are hosting a nutrition seminar, discussing healthy eating habits. Speak with a knowledgeable and enthusiastic tone, maintaining a moderate pace. Your voice should be clear and informative, with an undertone of passion for healthy living. /div> div classdialogue-line> Welcome, everyone! Today, were diving into the world of healthy eating habits. Its crucial to understand how our diet impacts our overall well-being. Lets start with the basics: what are the essential components of a balanced diet? /div> /div> div classscript-text> strong>Prompt 4:/strong> div classstage-direction> Stage directions: SITUATION: Speaking in a Quiet Library: You are a student defending your thesis. Speak with a nervous, slightly shaky tone at a moderate pace, ensuring clear articulation. Your voice should sound anxious yet determined, appropriate for a formal academic setting. /div> div classdialogue-line> Professor, Ive been researching the effects of social media on mental health, focusing on anxiety and depression among young adults. My findings suggest a significant correlation between excessive social media use and increased symptoms of these conditions. /div> /div> div classscript-text> strong>Prompt 5:/strong> div classstage-direction> Stage directions: ROLE: Knowledgeable Professor You are a middle-aged male professor giving a lecture on quantum computing. Speak with a slower pace and a confident tone, ensuring clear articulation and measured intonation. Delivering content with a slow, confident pace /div> div classdialogue-line> Welcome, everyone, to todays lecture on quantum computing. Well explore the principles of superposition and entanglement, and how they enable quantum computers to perform certain calculations much faster than classical computers. /div> /div> div classscript-text> strong>Prompt 6:/strong> div classstage-direction> Stage directions: maintaining a slow, confident delivery /div> div classdialogue-line> Of course. Superposition allows quantum bits, or qubits, to exist in multiple states simultaneously. This is unlike classical bits, which can only be in one state at a time. sighs Lets take a closer look at this phenomenon. /div> /div> div classscript-text> strong>Prompt 7:/strong> div classstage-direction> Stage directions: ROLE: Nervous Candidate You are a young adult candidate discussing your qualifications in a job interview. Speaking with a slightly nervous and fast pace /div> div classdialogue-line> Um, yes, I have a Bachelors degree in Business Administration and I recently completed a certification in Digital Marketing. sighs /div> /div> div classscript-text> strong>Prompt 8:/strong> div classstage-direction> Stage directions: speaking with a more controlled and steady voice /div> div classdialogue-line> Okay, I understand. I have worked as a Marketing Coordinator for two years at XYZ Corp, where I managed social media campaigns and analyzed market trends. /div> /div> div classscript-text> strong>Prompt 9:/strong> div classstage-direction> Stage directions: ROLE: Player You are apologizing to an opponent for making an incorrect move in a game. Speaking with a slow, low-pitched, and soft tone /div> div classdialogue-line> Im so sorry, I didnt realize it would be such a bad move. sighs Ill try to do better. /div> /div> div classscript-text> strong>Prompt 10:/strong> div classstage-direction> Stage directions: speaking with a gentle, slower pace /div> div classdialogue-line> I understand, and Im truly sorry. Could you please slow down a bit? Its hard to keep up with your pace. /div> /div> /div> !-- Recording Controls at Bottom --> div classrecording-controls idrecordingControlsBottom styledisplay: none;> h3>π€ Recording Controls - Bottom/h3> button typebutton idrecordButton2 onclicktoggleRecording() disabled> π€ Start Recording /button> button typebutton idpauseButton2 onclickpauseRecording() disabled stylebackground: #ffc107;> βΈοΈ Pause /button> button typebutton idresetButton2 onclickresetRecording() disabled> π Reset Recording /button> /div> div idstatus classstatus styledisplay: none;>/div> div idaudioPreview classaudio-preview styledisplay: none;> h4>π§ Review Your Recording/h4> audio idaudioPlayer controls>/audio> br> button typebutton idsubmitButton onclicksubmitAudition() disabled> π€ Submit Audition /button> /div> /div> !-- Thank You Page (hidden initially) --> div idthankYouPage classhidden> div classlogo> div classlogo-circle> div classlogo-text>c8c.ai/div> /div> h2>π Thank You!/h2> p stylefont-size: 18px;>Your audition has been successfully submitted./p> /div> div classfeedback-section> h3 styletext-align: center;>π Help Us Improve/h3> p styletext-align: center;>Please share your feedback about the audition process:/p> form idfeedbackForm> div classform-group> label forfeedbackRating>How would you rate your experience? */label> select idfeedbackRating required> option value>Select rating.../option> option value5>βββββ Excellent/option> option value4>ββββ Good/option> option value3>βββ Average/option> option value2>ββ Poor/option> option value1>β Very Poor/option> /select> /div> div classform-group> label forfeedbackText>Any comments or suggestions?/label> textarea idfeedbackText rows4 stylewidth: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; placeholderTell us about your experience...>/textarea> /div> div styletext-align: center;> button typebutton onclicksubmitFeedback() stylebackground: #007bff; margin-right: 10px;> π€ Submit Feedback /button> button typebutton onclickskipFeedback() stylebackground: #6c757d;> Skip /button> /div> /form> /div> !-- Referral Section --> div stylebackground: #e8f5e8; padding: 30px; border-radius: 10px; margin: 30px 0; border-left: 4px solid #28a745;> h3 styletext-align: center; margin-bottom: 20px; color: #28a745;>π€ Know Someone Who Might Be Interested?/h3> p styletext-align: center; margin-bottom: 20px; color: #333;> Help us find more talented voices! If you know anyone else who might be interested in participating in our voice casting, please let us know and well contact them. /p> form idreferralForm stylemax-width: 500px; margin: 0 auto;> div classform-group> label forreferralName>Their Name/label> input typetext idreferralName stylewidth: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; placeholdere.g., John Smith> /div> div classform-group> label forreferralEmail>Their Email Address/label> input typeemail idreferralEmail stylewidth: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; placeholdere.g., john@example.com> /div> div classform-group> label forreferralNote>Optional Note/label> textarea idreferralNote rows3 stylewidth: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; placeholderTell us why you think theyd be great for voice casting...>/textarea> /div> div styletext-align: center;> button typebutton onclicksubmitReferral() stylebackground: #28a745; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 16px;> π§ Send Referral /button> /div> /form> /div> div styletext-align: center;> p>Well be in touch if youre selected for the next stage./p> button typebutton onclickstartNewAudition() stylebackground: #28a745;> π¬ Record Another Audition /button> /div> /div> !-- Line-by-Line Recording Page (hidden initially) --> div idlineByLineContent classhidden> div classlogo> div classlogo-circle> div classlogo-text>c8c.ai/div> /div> h1>π Line-by-Line Recording/h1> p>Record each prompt individually, then combine them into one submission/p> /div> div stylebackground: #e8f5e8; padding: 15px; border-radius: 5px; margin: 20px 0; border-left: 4px solid #28a745;> strong>π Instructions:/strong>br> β’ Record each line individuallybr> β’ You can re-record any line as many times as neededbr> β’ Once all 10 lines are recorded, click Combine All Linesbr> β’ Review the combined audio before submitting /div> div idlineProgress stylebackground: #f8f9fa; padding: 15px; border-radius: 5px; margin: 20px 0;> strong>Progress: span idprogressCount>0/span>/10 lines recorded/strong> div stylebackground: #dee2e6; height: 20px; border-radius: 10px; margin-top: 10px;> div idprogressBar stylebackground: #28a745; height: 100%; border-radius: 10px; width: 0%; transition: width 0.3s;>/div> /div> /div> div idlinesContainer> !-- Individual line recording interfaces will be generated here --> /div> div idcombineSection styledisplay: none; text-align: center; margin: 30px 0; padding: 20px; background: #f8f9fa; border-radius: 5px;> h3>π΅ Combine All Lines/h3> p>All 10 lines have been recorded! Click below to combine them with 2-second gaps./p> button typebutton idcombineButton onclickcombineAllLines() stylebackground: #28a745; font-size: 18px; padding: 15px 30px;> π Combine All Lines /button> /div> div idfinalAudioSection styledisplay: none; text-align: center; margin: 30px 0; padding: 20px; background: #f8f9fa; border-radius: 5px;> h3>π§ Combined Audio/h3> audio idfinalAudioPlayer controls stylewidth: 100%; margin: 20px 0;>/audio> br> button typebutton idsubmitLineByLineButton onclicksubmitLineByLineAudition() stylebackground: #007bff; font-size: 18px; padding: 15px 30px; margin: 10px;> π€ Submit Combined Audition /button> /div> !-- Instructions Section --> div ideditInstructions styledisplay: none; text-align: center; margin: 20px 0; padding: 20px; background: #fff3cd; border-radius: 5px; border-left: 4px solid #ffc107;> h4 stylecolor: #856404; margin-bottom: 15px;>π Want to Perfect Your Recording?/h4> p stylecolor: #856404; margin: 0; line-height: 1.5;> You can edit any line by clicking the Start Recording button under that specific line, then hit Re-combine to merge all lines again. Once youre satisfied with the final result, just hit Submit Combined Audition! /p> /div> div styletext-align: center; margin: 30px 0;> button typebutton onclickbackToMainForm() stylebackground: #6c757d;> β Back to Form /button> /div> /div> !-- Continuous Recording Page (hidden initially) --> div idcontinuousContent classhidden> div classlogo> div classlogo-circle> div classlogo-text>c8c.ai/div> /div> h1>π€ Continuous Recording/h1> p>Record all 10 prompts in one continuous session/p> /div> !-- Recording Controls - Top --> div classrecording-controls styletext-align: center; margin: 30px 0; padding: 20px; background: #f8f9fa; border-radius: 5px;> h3>π€ Recording Controls - Top/h3> p>Click Start Recording and read all the prompts below in one continuous session./p> button typebutton idcontinuousRecordButton onclicktoggleContinuousRecording() stylebackground: #28a745; color: white; border: none; padding: 20px 40px; border-radius: 5px; font-size: 18px; margin: 10px;> π€ Start Recording /button> button typebutton idcontinuousPauseButton onclickpauseContinuousRecording() disabled stylebackground: #ffc107; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 16px; margin: 10px;> βΈοΈ Pause /button> button typebutton idcontinuousResetButton onclickresetContinuousRecording() disabled stylebackground: #6c757d; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 16px; margin: 10px;> π Reset Recording /button> /div> div idcontinuousStatus classstatus styledisplay: none;>/div> !-- Script Content --> div classscript-section> h3>π The Script - All Prompts/h3> p>strong>Record all prompts below in one continuous session, following each stage direction./strong>/p> div classscript-text> strong>Prompt 1:/strong> div classstage-direction> Stage directions: Romantic Book Reader You are reading a book during a library storytime event. Speak with a lively, enthusiastic tone, using a slightly faster pace and dynamic prosody /div> div classdialogue-line> Hello everyone! Today, Im thrilled to share my thoughts on The Notebook by Nicholas Sparks. This book is an absolute gem, filled with love, passion, and unforgettable moments. /div> /div> div classscript-text> strong>Prompt 2:/strong> div classstage-direction> Stage directions: maintain a fast pace with dynamic prosody /div> div classdialogue-line> From the very first page, youre drawn into the story of Noah and Allie, two young lovers whose romance is as intense as it is beautiful. Their love story is one for the ages! /div> /div> div classscript-text> strong>Prompt 3:/strong> div classstage-direction> Stage directions: Fitness Trainer You are hosting a nutrition seminar, discussing healthy eating habits. Speak with a knowledgeable and enthusiastic tone, maintaining a moderate pace. Your voice should be clear and informative, with an undertone of passion for healthy living. /div> div classdialogue-line> Welcome, everyone! Today, were diving into the world of healthy eating habits. Its crucial to understand how our diet impacts our overall well-being. Lets start with the basics: what are the essential components of a balanced diet? /div> /div> div classscript-text> strong>Prompt 4:/strong> div classstage-direction> Stage directions: SITUATION: Speaking in a Quiet Library: You are a student defending your thesis. Speak with a nervous, slightly shaky tone at a moderate pace, ensuring clear articulation. Your voice should sound anxious yet determined, appropriate for a formal academic setting. /div> div classdialogue-line> Professor, Ive been researching the effects of social media on mental health, focusing on anxiety and depression among young adults. My findings suggest a significant correlation between excessive social media use and increased symptoms of these conditions. /div> /div> div classscript-text> strong>Prompt 5:/strong> div classstage-direction> Stage directions: ROLE: Knowledgeable Professor You are a middle-aged male professor giving a lecture on quantum computing. Speak with a slower pace and a confident tone, ensuring clear articulation and measured intonation. Delivering content with a slow, confident pace /div> div classdialogue-line> Welcome, everyone, to todays lecture on quantum computing. Well explore the principles of superposition and entanglement, and how they enable quantum computers to perform certain calculations much faster than classical computers. /div> /div> div classscript-text> strong>Prompt 6:/strong> div classstage-direction> Stage directions: maintaining a slow, confident delivery /div> div classdialogue-line> Of course. Superposition allows quantum bits, or qubits, to exist in multiple states simultaneously. This is unlike classical bits, which can only be in one state at a time. sighs Lets take a closer look at this phenomenon. /div> /div> div classscript-text> strong>Prompt 7:/strong> div classstage-direction> Stage directions: ROLE: Nervous Candidate You are a young adult candidate discussing your qualifications in a job interview. Speaking with a slightly nervous and fast pace /div> div classdialogue-line> Um, yes, I have a Bachelors degree in Business Administration and I recently completed a certification in Digital Marketing. sighs /div> /div> div classscript-text> strong>Prompt 8:/strong> div classstage-direction> Stage directions: speaking with a more controlled and steady voice /div> div classdialogue-line> Okay, I understand. I have worked as a Marketing Coordinator for two years at XYZ Corp, where I managed social media campaigns and analyzed market trends. /div> /div> div classscript-text> strong>Prompt 9:/strong> div classstage-direction> Stage directions: ROLE: Player You are apologizing to an opponent for making an incorrect move in a game. Speaking with a slow, low-pitched, and soft tone /div> div classdialogue-line> Im so sorry, I didnt realize it would be such a bad move. sighs Ill try to do better. /div> /div> div classscript-text> strong>Prompt 10:/strong> div classstage-direction> Stage directions: speaking with a gentle, slower pace /div> div classdialogue-line> I understand, and Im truly sorry. Could you please slow down a bit? Its hard to keep up with your pace. /div> /div> /div> !-- Recording Controls - Bottom --> div classrecording-controls styletext-align: center; margin: 30px 0; padding: 20px; background: #f8f9fa; border-radius: 5px;> h3>π€ Recording Controls - Bottom/h3> button typebutton idcontinuousRecordButton2 onclicktoggleContinuousRecording() stylebackground: #28a745; color: white; border: none; padding: 20px 40px; border-radius: 5px; font-size: 18px; margin: 10px;> π€ Start Recording /button> button typebutton idcontinuousPauseButton2 onclickpauseContinuousRecording() disabled stylebackground: #ffc107; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 16px; margin: 10px;> βΈοΈ Pause /button> button typebutton idcontinuousResetButton2 onclickresetContinuousRecording() disabled stylebackground: #6c757d; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 16px; margin: 10px;> π Reset Recording /button> /div> div idcontinuousAudioPreview classaudio-preview styledisplay: none;> h4>π§ Review Your Recording/h4> audio idcontinuousAudioPlayer controls stylewidth: 100%; margin: 10px 0;>/audio> br> button typebutton idsubmitContinuousButton onclicksubmitContinuousAudition() stylebackground: #007bff; color: white; border: none; padding: 15px 30px; border-radius: 5px; font-size: 18px; margin: 10px;> π€ Submit Audition /button> /div> div styletext-align: center; margin: 30px 0;> button typebutton onclickbackToMainFormFromContinuous() stylebackground: #6c757d; color: white; border: none; padding: 10px 20px; border-radius: 5px;> β Back to Form /button> /div> /div> /div> script> // API Configuration const API_BASE https://c8c-auditions-backend-production-ae15.up.railway.app; // Global variables let mediaRecorder; let audioChunks ; let recordedBlob null; let isRecording false; let isPaused false; let storedRecaptchaToken null; // Initialize document.addEventListener(DOMContentLoaded, function() { checkMicrophonePermission(); }); function startContinuousMode() { console.log(startContinuousMode called); // Validate form first const firstName document.getElementById(firstName).value.trim(); const lastName document.getElementById(lastName).value.trim(); const email document.getElementById(email).value.trim(); const phone document.getElementById(phone).value.trim(); const age document.getElementById(age).value; const sex document.getElementById(sex).value; const location document.getElementById(location).value; console.log(Form values:, {firstName, lastName, email, phone, age, sex, location}); if (!firstName || !lastName || !email || !age || !sex || !location) { alert(Please fill in all required fields before proceeding.); return; } // Validate age range if (age 18 || age > 99) { alert(Age must be between 18 and 99.); return; } // reCAPTCHA validation removed storedRecaptchaToken null; console.log(About to call showContinuousRecording); showContinuousRecording(); } function startLineByLineRecording() { // Validate form first const firstName document.getElementById(firstName).value.trim(); const lastName document.getElementById(lastName).value.trim(); const email document.getElementById(email).value.trim(); const phone document.getElementById(phone).value.trim(); const age document.getElementById(age).value; const sex document.getElementById(sex).value; const location document.getElementById(location).value; if (!firstName || !lastName || !email || !age || !sex || !location) { alert(Please fill in all required fields before proceeding.); return; } // Validate age range if (age 18 || age > 99) { alert(Age must be between 18 and 99.); return; } // reCAPTCHA validation removed storedRecaptchaToken null; showLineByLineRecording(); } function showContinuousRecording() { console.log(showContinuousRecording called); // Hide main content and show continuous recording interface document.getElementById(mainContent).style.display none; document.getElementById(continuousContent).style.display block; console.log(Page switched to continuous content); // Scroll to top window.scrollTo(0, 0); // Use the same status function that works for line-by-line showStatus(β Continuous recording mode selected! Record all prompts in one take., success); } function showLineByLineRecording() { // Hide main content and show line-by-line interface document.getElementById(mainContent).style.display none; document.getElementById(lineByLineContent).style.display block; // Scroll to top window.scrollTo(0, 0); // Initialize line-by-line recording initializeLineByLineRecording(); showStatus(β Line-by-line recording mode selected! Record each prompt individually., success); } async function checkMicrophonePermission() { try { const stream await navigator.mediaDevices.getUserMedia({ audio: true }); stream.getTracks().forEach(track > track.stop()); showStatus(π€ Microphone access granted. Ready to record!, success); } catch (error) { showStatus(β Microphone access denied. Please allow microphone access to record your audition., error); } } async function toggleRecording() { if (!isRecording) { await startRecording(); } else { stopRecording(); } } async function startRecording() { try { // Track recording started gtag(event, recording_started, { event_category: engagement, event_label: english_portal }); const stream await navigator.mediaDevices.getUserMedia({ audio: { sampleRate: 44100, channelCount: 1, volume: 1.0 } }); // Force MP4 audio format for consistency let options ; if (MediaRecorder.isTypeSupported(audio/wav)) { options.push({mimeType: audio/wav}); } else if (MediaRecorder.isTypeSupported(audio/webm)) { options.push({mimeType: audio/webm}); } else { // Fallback for browsers that dont support WAV console.warn(WAV not supported, using browser default); } console.log(Using audio format:, options0?.mimeType || default); mediaRecorder new MediaRecorder(stream, options0 || {}); audioChunks ; mediaRecorder.ondataavailable (event) > { if (event.data.size > 0) { audioChunks.push(event.data); } }; mediaRecorder.onstop () > { const mimeType mediaRecorder.mimeType || audio/wav; const audioBlob new Blob(audioChunks, { type: mimeType }); recordedBlob audioBlob; const audioUrl URL.createObjectURL(audioBlob); const audioPlayer document.getElementById(audioPlayer); audioPlayer.src audioUrl; audioPlayer.load(); document.getElementById(audioPreview).style.display block; document.getElementById(submitButton).disabled false; stream.getTracks().forEach(track > track.stop()); }; mediaRecorder.start(100); isRecording true; const recordButton document.getElementById(recordButton); const recordButton2 document.getElementById(recordButton2); recordButton.textContent βΉοΈ Stop Recording; recordButton2.textContent βΉοΈ Stop Recording; recordButton.classList.add(recording); recordButton2.classList.add(recording); document.getElementById(pauseButton).disabled false; document.getElementById(pauseButton2).disabled false; document.getElementById(resetButton).disabled false; document.getElementById(resetButton2).disabled false; showStatus(π΄ Recording in progress... Read all the prompts above., info); } catch (error) { console.error(Error starting recording:, error); showStatus(β Error starting recording: + error.message, error); } } function stopRecording() { if (mediaRecorder && isRecording) { mediaRecorder.stop(); isRecording false; // Track recording completed gtag(event, recording_completed, { event_category: engagement, event_label: english_portal }); const recordButton document.getElementById(recordButton); const recordButton2 document.getElementById(recordButton2); recordButton.textContent π€ Start Recording; recordButton2.textContent π€ Start Recording; recordButton.classList.remove(recording); recordButton2.classList.remove(recording); document.getElementById(pauseButton).disabled true; document.getElementById(pauseButton2).disabled true; showStatus(β Recording completed! Review your audio below., success); } } function resetRecording() { if (isRecording) { stopRecording(); } audioChunks ; recordedBlob null; isPaused false; document.getElementById(audioPreview).style.display none; document.getElementById(submitButton).disabled true; document.getElementById(resetButton).disabled true; document.getElementById(resetButton2).disabled true; const recordButton document.getElementById(recordButton); const recordButton2 document.getElementById(recordButton2); recordButton.textContent π€ Start Recording; recordButton2.textContent π€ Start Recording; recordButton.classList.remove(recording); recordButton2.classList.remove(recording); showStatus(π Recording reset. Ready to record again., info); } function pauseRecording() { if (mediaRecorder && isRecording && !isPaused) { mediaRecorder.pause(); isPaused true; const recordButton document.getElementById(recordButton); const recordButton2 document.getElementById(recordButton2); recordButton.textContent βΆοΈ Resume; recordButton2.textContent βΆοΈ Resume; document.getElementById(pauseButton).disabled true; document.getElementById(pauseButton2).disabled true; showStatus(βΈοΈ Recording paused, info); } else if (mediaRecorder && isPaused) { mediaRecorder.resume(); isPaused false; const recordButton document.getElementById(recordButton); const recordButton2 document.getElementById(recordButton2); recordButton.textContent βΉοΈ Stop Recording; recordButton2.textContent βΉοΈ Stop Recording; document.getElementById(pauseButton).disabled false; document.getElementById(pauseButton2).disabled false; showStatus(π΄ Recording resumed..., info); } } async function submitAudition() { // Track submission attempted gtag(event, submission_attempted, { event_category: engagement, event_label: english_portal }); if (!recordedBlob) { showStatus(β No recording found. Please record your audition first., error); gtag(event, submission_failed, { event_category: errors, event_label: no_recording }); return; } // Validate form const firstName document.getElementById(firstName).value.trim(); const lastName document.getElementById(lastName).value.trim(); const email document.getElementById(email).value.trim(); const phone document.getElementById(phone).value.trim(); const age document.getElementById(age).value; const sex document.getElementById(sex).value; const location document.getElementById(location).value; if (!firstName || !lastName || !email || !age || !sex || !location) { showStatus(β Please fill in all required fields., error); gtag(event, submission_failed, { event_category: errors, event_label: missing_fields }); return; } document.getElementById(submitButton).disabled true; showStatus(β³ Preparing upload..., info); try { const audioBlob recordedBlob; const actualMimeType audioBlob.type; // Force MP4 format for consistency let fileExtension .mp4; let contentType actualMimeType || audio/wav; const timestamp new Date().toISOString().replace(/:./g, -); const sanitizedName `${firstName}_${lastName}`.replace(/^a-zA-Z0-9/g, _); const filename `auditions/EN_${sanitizedName}_${age}_${sex}_${location}_${timestamp}${fileExtension}`; const metadata { applicant-firstname: firstName, applicant-lastname: lastName, applicant-name: `${firstName} ${lastName}`, applicant-email: email, applicant-phone: phone || , applicant-age: age.toString(), applicant-sex: sex, applicant-location: location, applicant-language: English, recording-mode: full, upload-timestamp: new Date().toISOString(), project-number: 2094 }; showStatus(π Getting upload URL..., info); const urlResponse await fetch(`${API_BASE}/api/upload-url`, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ filename: filename, contentType: contentType, metadata: metadata, recaptchaToken: null }) }); const urlResult await urlResponse.json(); if (!urlResult.success) { throw new Error(urlResult.error || Failed to get upload URL); } showStatus(π€ Uploading your audition..., info); const uploadResponse await fetch(urlResult.uploadUrl, { method: PUT, body: audioBlob, headers: { Content-Type: contentType } }); if (!uploadResponse.ok) { throw new Error(`Upload failed: ${uploadResponse.statusText}`); } showStatus(β Audition submitted successfully!, success); // Track successful submission gtag(event, submission_success, { event_category: conversions, event_label: english_portal, value: 1 }); // Show thank you page setTimeout(() > { showThankYouPage(); }, 2000); } catch (error) { console.error(Upload error:, error); showStatus(β Upload failed: + error.message, error); document.getElementById(submitButton).disabled false; // Track submission error gtag(event, submission_error, { event_category: errors, event_label: error.message }); } } function showStatus(message, type) { const statusDiv document.getElementById(status); statusDiv.textContent message; statusDiv.className `status ${type}`; statusDiv.style.display block; if (type success) { setTimeout(() > { statusDiv.style.display none; }, 10000); } } function showThankYouPage() { document.getElementById(mainContent).classList.add(hidden); document.getElementById(thankYouPage).classList.remove(hidden); window.scrollTo(0, 0); } async function submitFeedback() { const rating document.getElementById(feedbackRating).value; const feedback document.getElementById(feedbackText).value.trim(); if (!rating) { alert(Please select a rating before submitting.); return; } try { const firstName document.getElementById(firstName).value.trim(); const lastName document.getElementById(lastName).value.trim(); const email document.getElementById(email).value.trim(); const feedbackData { rating: parseInt(rating), feedback: feedback, firstName: firstName, lastName: lastName, email: email, timestamp: new Date().toISOString(), type: audition_feedback }; const filename `feedback/feedback_${firstName}_${lastName}_${new Date().toISOString().replace(/:./g, -)}.json`; const uploadResponse await fetch(`${API_BASE}/api/upload-url`, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ filename: filename, contentType: application/json, metadata: { feedback-type: audition } }) }); const urlResult await uploadResponse.json(); if (urlResult.success) { await fetch(urlResult.uploadUrl, { method: PUT, body: JSON.stringify(feedbackData), headers: { Content-Type: application/json } }); } document.getElementById(feedbackForm).innerHTML div styletext-align: center; color: #28a745; font-weight: bold;>β Thank you for your feedback!/div>; } catch (error) { console.error(Feedback submission error:, error); alert(Thank you for your feedback!); } } function skipFeedback() { document.getElementById(feedbackForm).innerHTML div styletext-align: center; color: #6c757d;>Feedback skipped - thank you for your audition!/div>; } async function submitReferral() { const referralName document.getElementById(referralName).value.trim(); const referralEmail document.getElementById(referralEmail).value.trim(); const referralNote document.getElementById(referralNote).value.trim(); if (!referralName || !referralEmail) { alert(Please provide both name and email address for the referral.); return; } try { // Get referrer info from original form const referrerFirstName document.getElementById(firstName).value.trim(); const referrerLastName document.getElementById(lastName).value.trim(); const referrerEmail document.getElementById(email).value.trim(); const referralData { referralName: referralName, referralEmail: referralEmail, referralNote: referralNote, referrerName: `${referrerFirstName} ${referrerLastName}`, referrerEmail: referrerEmail, timestamp: new Date().toISOString(), type: voice_casting_referral }; // Save referral to S3 via backend const filename `referrals/referral_${referralName.replace(/^a-zA-Z0-9/g, _)}_${new Date().toISOString().replace(/:./g, -)}.json`; const uploadResponse await fetch(`${API_BASE}/api/upload-url`, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ filename: filename, contentType: application/json, metadata: { referral-type: voice_casting } }) }); const urlResult await uploadResponse.json(); if (urlResult.success) { await fetch(urlResult.uploadUrl, { method: PUT, body: JSON.stringify(referralData), headers: { Content-Type: application/json } }); } document.getElementById(referralForm).innerHTML div styletext-align: center; color: #28a745; font-weight: bold; padding: 20px;>β Thank you! We\ll reach out to them about our voice casting opportunities./div>; } catch (error) { console.error(Referral submission error:, error); document.getElementById(referralForm).innerHTML div styletext-align: center; color: #28a745; font-weight: bold; padding: 20px;>β Thank you for the referral!/div>; } } function startNewAudition() { document.getElementById(thankYouPage).classList.add(hidden); document.getElementById(mainContent).classList.remove(hidden); document.getElementById(auditionForm).reset(); resetRecording(); document.getElementById(recordingControlsTop).style.display none; document.getElementById(recordingControlsBottom).style.display none; document.getElementById(scriptContent).style.display none; document.getElementById(readyButton).style.display block; window.scrollTo(0, 0); } // Line-by-Line Recording Functions const scriptLines { id: 1, title: Prompt 1, stage: Romantic Book Reader You are reading a book during a library storytime event. Speak with a lively, enthusiastic tone, using a slightly faster pace and dynamic prosody, dialogue: Hello everyone! Today, Im thrilled to share my thoughts on The Notebook by Nicholas Sparks. This book is an absolute gem, filled with love, passion, and unforgettable moments. }, { id: 2, title: Prompt 2, stage: maintain a fast pace with dynamic prosody, dialogue: From the very first page, youre drawn into the story of Noah and Allie, two young lovers whose romance is as intense as it is beautiful. Their love story is one for the ages! }, { id: 3, title: Prompt 3, stage: Fitness Trainer You are hosting a nutrition seminar, discussing healthy eating habits. Speak with a knowledgeable and enthusiastic tone, maintaining a moderate pace. Your voice should be clear and informative, with an undertone of passion for healthy living., dialogue: Welcome, everyone! Today, were diving into the world of healthy eating habits. Its crucial to understand how our diet impacts our overall well-being. Lets start with the basics: what are the essential components of a balanced diet? }, { id: 4, title: Prompt 4, stage: SITUATION: Speaking in a Quiet Library: You are a student defending your thesis. Speak with a nervous, slightly shaky tone at a moderate pace, ensuring clear articulation. Your voice should sound anxious yet determined, appropriate for a formal academic setting., dialogue: Professor, Ive been researching the effects of social media on mental health, focusing on anxiety and depression among young adults. My findings suggest a significant correlation between excessive social media use and increased symptoms of these conditions. }, { id: 5, title: Prompt 5, stage: ROLE: Knowledgeable Professor You are a middle-aged male professor giving a lecture on quantum computing. Speak with a slower pace and a confident tone, ensuring clear articulation and measured intonation. Delivering content with a slow, confident pace, dialogue: Welcome, everyone, to todays lecture on quantum computing. Well explore the principles of superposition and entanglement, and how they enable quantum computers to perform certain calculations much faster than classical computers. }, { id: 6, title: Prompt 6, stage: maintaining a slow, confident delivery, dialogue: Of course. Superposition allows quantum bits, or qubits, to exist in multiple states simultaneously. This is unlike classical bits, which can only be in one state at a time. sighs Lets take a closer look at this phenomenon. }, { id: 7, title: Prompt 7, stage: ROLE: Nervous Candidate You are a young adult candidate discussing your qualifications in a job interview. Speaking with a slightly nervous and fast pace, dialogue: Um, yes, I have a Bachelors degree in Business Administration and I recently completed a certification in Digital Marketing. sighs }, { id: 8, title: Prompt 8, stage: speaking with a more controlled and steady voice, dialogue: Okay, I understand. I have worked as a Marketing Coordinator for two years at XYZ Corp, where I managed social media campaigns and analyzed market trends. }, { id: 9, title: Prompt 9, stage: ROLE: Player You are apologizing to an opponent for making an incorrect move in a game. Speaking with a slow, low-pitched, and soft tone, dialogue: Im so sorry, I didnt realize it would be such a bad move. sighs Ill try to do better. }, { id: 10, title: Prompt 10, stage: speaking with a gentle, slower pace, dialogue: I understand, and Im truly sorry. Could you please slow down a bit? Its hard to keep up with your pace. } ; let lineRecordings {}; // Store individual line recordings let combinedAudio null; let currentRecordingLine null; let lineMediaRecorder null; let lineAudioChunks ; let hasCombinedBefore false; // Track if weve combined at least once function initializeLineByLineRecording() { const container document.getElementById(linesContainer); container.innerHTML ; scriptLines.forEach(line > { const lineDiv document.createElement(div); lineDiv.className line-recording-item; lineDiv.style.cssText margin: 20px 0; padding: 20px; background: white; border-radius: 5px; border: 1px solid #dee2e6;; lineDiv.innerHTML ` div stylemargin-bottom: 15px;> h4>${line.title}/h4> div stylebackground: #f8f9fa; color: #666; font-style: italic; padding: 8px 12px; border-radius: 3px; margin: 5px 0; border-left: 3px solid #007bff; font-size: 14px;> Stage directions: ${line.stage} /div> div stylebackground: #fff3cd; color: #856404; font-weight: bold; padding: 12px 15px; border-radius: 5px; margin: 8px 0; border-left: 4px solid #ffc107; font-size: 16px; line-height: 1.4;> ${line.dialogue} /div> /div> div styletext-align: center; margin: 15px 0;> button typebutton idrecordBtn${line.id} onclicktoggleLineRecording(${line.id}) stylebackground: #28a745; color: white; border: none; padding: 15px 30px; border-radius: 5px; margin: 5px; font-size: 16px;> π€ Start Recording /button> button typebutton idplayBtn${line.id} onclickplayLineRecording(${line.id}) disabled stylebackground: #007bff; color: white; border: none; padding: 10px 20px; border-radius: 5px; margin: 5px;> βΆοΈ Play /button> /div> div idlineStatus${line.id} styletext-align: center; margin: 10px 0; font-weight: bold;> Not recorded /div> audio idlineAudio${line.id} styledisplay: none;>/audio> `; container.appendChild(lineDiv); }); updateProgress(); } async function toggleLineRecording(lineId) { // If this line is currently recording, stop it if (currentRecordingLine lineId && lineMediaRecorder) { lineMediaRecorder.stop(); return; } // If another line is recording, stop it first if (currentRecordingLine && currentRecordingLine ! lineId) { lineMediaRecorder.stop(); // Wait a moment for the stop to process await new Promise(resolve > setTimeout(resolve, 100)); } try { const stream await navigator.mediaDevices.getUserMedia({ audio: { sampleRate: 44100, channelCount: 1, volume: 1.0 } }); let options ; if (MediaRecorder.isTypeSupported(audio/wav)) { options.push({mimeType: audio/wav}); } else if (MediaRecorder.isTypeSupported(audio/webm)) { options.push({mimeType: audio/webm}); } else { console.warn(WAV not supported, using browser default); } lineMediaRecorder new MediaRecorder(stream, options0 || {}); lineAudioChunks ; currentRecordingLine lineId; lineMediaRecorder.ondataavailable (event) > { if (event.data.size > 0) { lineAudioChunks.push(event.data); } }; lineMediaRecorder.onstop () > { const mimeType lineMediaRecorder.mimeType || audio/wav; const audioBlob new Blob(lineAudioChunks, { type: mimeType }); // Check if this was a re-recording (line already had audio) const wasReRecording lineRecordingslineId ! undefined; // Store the new recording lineRecordingslineId audioBlob; const audioUrl URL.createObjectURL(audioBlob); const audioElement document.getElementById(`lineAudio${lineId}`); audioElement.src audioUrl; // Update UI for stopped recording - always show Re-record after first recording document.getElementById(`recordBtn${lineId}`).textContent π€ Re-record Line; document.getElementById(`recordBtn${lineId}`).style.background #28a745; // GREEN for re-record document.getElementById(`lineStatus${lineId}`).textContent β Recorded; document.getElementById(`lineStatus${lineId}`).style.color #28a745; document.getElementById(`playBtn${lineId}`).disabled false; stream.getTracks().forEach(track > track.stop()); currentRecordingLine null; updateProgress(); }; lineMediaRecorder.start(100); // Update UI for started recording - RED for stop document.getElementById(`recordBtn${lineId}`).textContent βΉοΈ Stop Recording; document.getElementById(`recordBtn${lineId}`).style.background #dc3545; // RED for stop document.getElementById(`lineStatus${lineId}`).textContent π΄ Recording...; document.getElementById(`lineStatus${lineId}`).style.color #dc3545; } catch (error) { console.error(Error starting line recording:, error); alert(Error starting recording: + error.message); } } function playLineRecording(lineId) { const audioElement document.getElementById(`lineAudio${lineId}`); audioElement.play(); } function updateProgress() { const recordedCount Object.keys(lineRecordings).length; document.getElementById(progressCount).textContent recordedCount; document.getElementById(progressBar).style.width (recordedCount / 10 * 100) + %; if (recordedCount 10) { document.getElementById(combineSection).style.display block; // If weve combined before and someone re-recorded, change to Re-combine if (hasCombinedBefore) { document.getElementById(combineButton).textContent π Re-Combine All Lines; document.getElementById(combineButton).style.background #ffc107; // Orange color for re-combine // Hide the final audio section since we need to re-combine document.getElementById(finalAudioSection).style.display none; } } else { document.getElementById(combineSection).style.display none; } } async function combineAllLines() { try { document.getElementById(combineButton).disabled true; document.getElementById(combineButton).textContent π Combining...; document.getElementById(combineButton).style.background #6c757d; // Gray while processing // Use AudioContext to properly combine WAV files const audioContext new (window.AudioContext || window.webkitAudioContext)(); const buffers ; // Convert WAV recordings to audio buffers for (let i 1; i 10; i++) { if (lineRecordingsi) { try { const arrayBuffer await lineRecordingsi.arrayBuffer(); const audioBuffer await audioContext.decodeAudioData(arrayBuffer); buffers.push(audioBuffer); } catch (error) { console.warn(`Failed to decode WAV for line ${i}:`, error); } } } // Combine buffers with gaps const sampleRate audioContext.sampleRate; const gapDuration 2; // seconds const gapSamples gapDuration * sampleRate; const totalSamples buffers.reduce((sum, buffer) > sum + buffer.length, 0) + (gapSamples * (buffers.length - 1)); const combinedBuffer audioContext.createBuffer(1, totalSamples, sampleRate); const output combinedBuffer.getChannelData(0); let offset 0; buffers.forEach((buffer, index) > { const input buffer.getChannelData(0); output.set(input, offset); offset + input.length; // Add gap (except after last buffer) if (index buffers.length - 1) { offset + gapSamples; } }); // Convert to WAV blob const wav audioBufferToWav(combinedBuffer); combinedAudio new Blob(wav, { type: audio/wav }); // Create URL and set to player const audioUrl URL.createObjectURL(combinedAudio); const audioPlayer document.getElementById(finalAudioPlayer); // Clean up any existing blob URL if (audioPlayer.src && audioPlayer.src.startsWith(blob:)) { URL.revokeObjectURL(audioPlayer.src); } audioPlayer.src audioUrl; audioPlayer.load(); // Force the audio element to load the new source // Add error handling for audio loading audioPlayer.onerror (e) > { console.error(Audio playback error:, e); console.error(Audio player error code:, audioPlayer.error?.code); console.error(Audio player error message:, audioPlayer.error?.message); }; audioPlayer.onloadeddata () > { console.log(Audio loaded successfully, duration:, audioPlayer.duration); }; document.getElementById(finalAudioSection).style.display block; console.log(Combined audio URL created:, audioUrl); console.log(Combined audio blob size:, combinedAudio.size, bytes); // Reset button to success state document.getElementById(combineButton).textContent β Combined Successfully!; document.getElementById(combineButton).style.background #28a745; document.getElementById(combineButton).disabled false; // Mark that weve combined before and show instructions hasCombinedBefore true; document.getElementById(editInstructions).style.display block; } catch (error) { console.error(Error combining audio:, error); alert(Error combining audio files. Please try again.); document.getElementById(combineButton).disabled false; document.getElementById(combineButton).textContent hasCombinedBefore ? π Re-Combine All Lines : π Combine All Lines; document.getElementById(combineButton).style.background hasCombinedBefore ? #ffc107 : #28a745; } } async function combineAudioBuffers(audioContext, recordings) { const buffers ; const sampleRate audioContext.sampleRate; let decodingErrors 0; // Convert all recordings to audio buffers for (let i 1; i 10; i++) { // English has 10 lines if (recordingsi) { try { const arrayBuffer await recordingsi.arrayBuffer(); const audioBuffer await audioContext.decodeAudioData(arrayBuffer); buffers.push(audioBuffer); } catch (error) { console.warn(`Failed to decode audio for line ${i}:`, error); decodingErrors++; // Skip this recording if it cant be decoded continue; } } } // If too many decoding errors, use simple blob concatenation fallback if (decodingErrors > 2) { console.log(Too many audio decoding errors, using simple blob concatenation); throw new Error(Audio decoding failed - using blob concatenation fallback); } // Calculate total length (including 2-second gaps) const gapDuration 2; // seconds const gapSamples gapDuration * sampleRate; const totalSamples buffers.reduce((sum, buffer) > sum + buffer.length, 0) + (gapSamples * (buffers.length - 1)); // Create combined buffer const combinedBuffer audioContext.createBuffer(1, totalSamples, sampleRate); const output combinedBuffer.getChannelData(0); let offset 0; buffers.forEach((buffer, index) > { const input buffer.getChannelData(0); output.set(input, offset); offset + input.length; // Add gap (except after last buffer) if (index buffers.length - 1) { offset + gapSamples; } }); return combinedBuffer; } function audioBufferToWav(buffer) { const length buffer.length; const sampleRate buffer.sampleRate; const arrayBuffer new ArrayBuffer(44 + length * 2); const view new DataView(arrayBuffer); // WAV header const writeString (offset, string) > { for (let i 0; i string.length; i++) { view.setUint8(offset + i, string.charCodeAt(i)); } }; writeString(0, RIFF); view.setUint32(4, 36 + length * 2, true); writeString(8, WAVE); writeString(12, fmt ); view.setUint32(16, 16, true); view.setUint16(20, 1, true); view.setUint16(22, 1, true); view.setUint32(24, sampleRate, true); view.setUint32(28, sampleRate * 2, true); view.setUint16(32, 2, true); view.setUint16(34, 16, true); writeString(36, data); view.setUint32(40, length * 2, true); // Convert float audio data to 16-bit PCM const channelData buffer.getChannelData(0); let offset 44; for (let i 0; i length; i++) { const sample Math.max(-1, Math.min(1, channelDatai)); view.setInt16(offset, sample * 0x7FFF, true); offset + 2; } return arrayBuffer; } async function submitLineByLineAudition() { if (!combinedAudio) { alert(Please combine all lines first.); return; } // Get form data const firstName document.getElementById(firstName).value.trim(); const lastName document.getElementById(lastName).value.trim(); const email document.getElementById(email).value.trim(); const phone document.getElementById(phone).value.trim(); const age document.getElementById(age).value; const sex document.getElementById(sex).value; const location document.getElementById(location).value; document.getElementById(submitLineByLineButton).disabled true; try { const timestamp new Date().toISOString().replace(/:./g, -); const sanitizedName `${firstName}_${lastName}`.replace(/^a-zA-Z0-9/g, _); const filename `auditions/EN_LINE_${sanitizedName}_${age}_${sex}_${location}_${timestamp}.wav`; const metadata { applicant-firstname: firstName, applicant-lastname: lastName, applicant-name: `${firstName} ${lastName}`, applicant-email: email, applicant-phone: phone || , applicant-age: age.toString(), applicant-sex: sex, applicant-location: location, applicant-language: English, recording-mode: line-by-line, upload-timestamp: new Date().toISOString(), project-number: 2094 }; const urlResponse await fetch(`${API_BASE}/api/upload-url`, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ filename: filename, contentType: audio/wav, metadata: metadata, recaptchaToken: null }) }); const urlResult await urlResponse.json(); if (!urlResult.success) { throw new Error(urlResult.error || Failed to get upload URL); } const uploadResponse await fetch(urlResult.uploadUrl, { method: PUT, body: combinedAudio, headers: { Content-Type: audio/wav } }); if (!uploadResponse.ok) { throw new Error(`Upload failed: ${uploadResponse.statusText}`); } // Show thank you page directly - no alert needed document.getElementById(lineByLineContent).style.display none; document.getElementById(thankYouPage).classList.remove(hidden); window.scrollTo(0, 0); } catch (error) { console.error(Upload error:, error); alert(β Upload failed: + error.message); document.getElementById(submitLineByLineButton).disabled false; } } function backToMainForm() { document.getElementById(lineByLineContent).style.display none; document.getElementById(mainContent).style.display block; document.getElementById(readyButton).style.display block; // Reset line-by-line data lineRecordings {}; combinedAudio null; hasCombinedBefore false; updateProgress(); } // Continuous Recording Functions let continuousMediaRecorder null; let continuousAudioChunks ; let continuousRecordedBlob null; let isContinuousRecording false; async function toggleContinuousRecording() { if (!isContinuousRecording) { await startContinuousRecording(); } else { stopContinuousRecording(); } } async function startContinuousRecording() { try { const stream await navigator.mediaDevices.getUserMedia({ audio: { sampleRate: 44100, channelCount: 1, volume: 1.0 } }); let options ; if (MediaRecorder.isTypeSupported(audio/wav)) { options.push({mimeType: audio/wav}); } else if (MediaRecorder.isTypeSupported(audio/webm)) { options.push({mimeType: audio/webm}); } else { console.warn(WAV not supported, using browser default); } continuousMediaRecorder new MediaRecorder(stream, options0 || {}); continuousAudioChunks ; isContinuousRecording true; continuousMediaRecorder.ondataavailable (event) > { if (event.data.size > 0) { continuousAudioChunks.push(event.data); } }; continuousMediaRecorder.onstop () > { const mimeType continuousMediaRecorder.mimeType || audio/wav; const audioBlob new Blob(continuousAudioChunks, { type: mimeType }); continuousRecordedBlob audioBlob; const audioUrl URL.createObjectURL(audioBlob); const audioPlayer document.getElementById(continuousAudioPlayer); audioPlayer.src audioUrl; audioPlayer.load(); document.getElementById(continuousAudioPreview).style.display block; // Update UI for stopped recording - GREEN for re-record document.getElementById(continuousRecordButton).textContent π€ Re-record; document.getElementById(continuousRecordButton).style.background #28a745; // GREEN for re-record document.getElementById(continuousRecordButton2).textContent π€ Re-record; document.getElementById(continuousRecordButton2).style.background #28a745; // GREEN for re-record document.getElementById(continuousResetButton).disabled false; document.getElementById(continuousResetButton2).disabled false; document.getElementById(continuousPauseButton).disabled true; document.getElementById(continuousPauseButton2).disabled true; stream.getTracks().forEach(track > track.stop()); isContinuousRecording false; showContinuousStatus(β Recording completed! Review your audio below., success); }; continuousMediaRecorder.start(100); // Update UI for started recording - RED for stop document.getElementById(continuousRecordButton).textContent βΉοΈ Stop Recording; document.getElementById(continuousRecordButton).style.background #dc3545; // RED for stop document.getElementById(continuousRecordButton2).textContent βΉοΈ Stop Recording; document.getElementById(continuousRecordButton2).style.background #dc3545; // RED for stop document.getElementById(continuousResetButton).disabled false; document.getElementById(continuousResetButton2).disabled false; document.getElementById(continuousPauseButton).disabled false; document.getElementById(continuousPauseButton2).disabled false; showContinuousStatus(π΄ Recording in progress... Read all the prompts below., info); } catch (error) { console.error(Error starting continuous recording:, error); showContinuousStatus(β Error starting recording: + error.message, error); } } function stopContinuousRecording() { if (continuousMediaRecorder && isContinuousRecording) { continuousMediaRecorder.stop(); } } function pauseContinuousRecording() { if (continuousMediaRecorder && isContinuousRecording && continuousMediaRecorder.state recording) { continuousMediaRecorder.pause(); // Update UI for paused recording document.getElementById(continuousRecordButton).textContent βΆοΈ Resume; document.getElementById(continuousRecordButton).style.background #28a745; // GREEN for resume document.getElementById(continuousRecordButton2).textContent βΆοΈ Resume; document.getElementById(continuousRecordButton2).style.background #28a745; // GREEN for resume document.getElementById(continuousPauseButton).disabled true; document.getElementById(continuousPauseButton2).disabled true; showContinuousStatus(βΈοΈ Recording paused, info); } else if (continuousMediaRecorder && continuousMediaRecorder.state paused) { continuousMediaRecorder.resume(); // Update UI for resumed recording document.getElementById(continuousRecordButton).textContent βΉοΈ Stop Recording; document.getElementById(continuousRecordButton).style.background #dc3545; // RED for stop document.getElementById(continuousRecordButton2).textContent βΉοΈ Stop Recording; document.getElementById(continuousRecordButton2).style.background #dc3545; // RED for stop document.getElementById(continuousPauseButton).disabled false; document.getElementById(continuousPauseButton2).disabled false; showContinuousStatus(π΄ Recording resumed..., info); } } function resetContinuousRecording() { if (isContinuousRecording) { stopContinuousRecording(); } continuousAudioChunks ; continuousRecordedBlob null; isContinuousRecording false; document.getElementById(continuousAudioPreview).style.display none; document.getElementById(continuousRecordButton).textContent π€ Start Recording; document.getElementById(continuousRecordButton).style.background #28a745; // GREEN for start document.getElementById(continuousRecordButton2).textContent π€ Start Recording; document.getElementById(continuousRecordButton2).style.background #28a745; // GREEN for start document.getElementById(continuousResetButton).disabled true; document.getElementById(continuousResetButton2).disabled true; document.getElementById(continuousPauseButton).disabled true; document.getElementById(continuousPauseButton2).disabled true; showContinuousStatus(π Recording reset. Ready to record again., info); } async function submitContinuousAudition() { if (!continuousRecordedBlob) { showContinuousStatus(β No recording found. Please record your audition first., error); return; } // Get form data const firstName document.getElementById(firstName).value.trim(); const lastName document.getElementById(lastName).value.trim(); const email document.getElementById(email).value.trim(); const phone document.getElementById(phone).value.trim(); const age document.getElementById(age).value; const sex document.getElementById(sex).value; const location document.getElementById(location).value; document.getElementById(submitContinuousButton).disabled true; showContinuousStatus(β³ Preparing upload..., info); try { const audioBlob continuousRecordedBlob; const actualMimeType audioBlob.type; // Force MP4 format for consistency let fileExtension .mp4; let contentType actualMimeType || audio/wav; const timestamp new Date().toISOString().replace(/:./g, -); const sanitizedName `${firstName}_${lastName}`.replace(/^a-zA-Z0-9/g, _); const filename `auditions/EN_CONT_${sanitizedName}_${age}_${sex}_${location}_${timestamp}${fileExtension}`; const metadata { applicant-firstname: firstName, applicant-lastname: lastName, applicant-name: `${firstName} ${lastName}`, applicant-email: email, applicant-phone: phone || , applicant-age: age.toString(), applicant-sex: sex, applicant-location: location, applicant-language: English, recording-mode: continuous, upload-timestamp: new Date().toISOString(), project-number: 2094 }; showContinuousStatus(π Getting upload URL..., info); const urlResponse await fetch(`${API_BASE}/api/upload-url`, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ filename: filename, contentType: contentType, metadata: metadata, recaptchaToken: null }) }); const urlResult await urlResponse.json(); if (!urlResult.success) { throw new Error(urlResult.error || Failed to get upload URL); } showContinuousStatus(π€ Uploading your audition..., info); const uploadResponse await fetch(urlResult.uploadUrl, { method: PUT, body: audioBlob, headers: { Content-Type: contentType } }); if (!uploadResponse.ok) { throw new Error(`Upload failed: ${uploadResponse.statusText}`); } // Show thank you page directly - no alert needed document.getElementById(continuousContent).style.display none; document.getElementById(thankYouPage).classList.remove(hidden); window.scrollTo(0, 0); } catch (error) { console.error(Upload error:, error); showContinuousStatus(β Upload failed: + error.message, error); document.getElementById(submitContinuousButton).disabled false; } } function showContinuousStatus(message, type) { const statusDiv document.getElementById(continuousStatus); statusDiv.textContent message; statusDiv.className `status ${type}`; statusDiv.style.display block; if (type success) { setTimeout(() > { statusDiv.style.display none; }, 10000); } } function backToMainFormFromContinuous() { document.getElementById(continuousContent).style.display none; document.getElementById(mainContent).style.display block; // Reset continuous recording data resetContinuousRecording(); window.scrollTo(0, 0); } /script>/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]