diff --git a/advanced/whisperx/README.md b/advanced/whisperx/README.md index 414115f..1fab36f 100644 --- a/advanced/whisperx/README.md +++ b/advanced/whisperx/README.md @@ -2,6 +2,8 @@ This example demonstrates how to run the WhisperX model on Lepton. [WhisperX](https://github.com/m-bain/whisperX) is similar to the whisper example, but does transcription, alignment, and diarization for the input. +The following example shows the WhisperX demo that allows one to very quickly recognize short audios. For long audios like podcasts, instead of having a long-waiting api, it is easier to build a service that does the actual recognition as a background task - see the notebook [What does a great podcast sound like?](audio_analysis.ipynb) as an end to end example. + ## Note on custom environment Similar to the Whisper JAX example, if you are running locally, we recommend you to use a custom environment like `conda` or `virtualenv`. diff --git a/advanced/whisperx/assets/negative_example.png b/advanced/whisperx/assets/negative_example.png new file mode 100644 index 0000000..6ef8284 Binary files /dev/null and b/advanced/whisperx/assets/negative_example.png differ diff --git a/advanced/whisperx/assets/positive_example.png b/advanced/whisperx/assets/positive_example.png new file mode 100644 index 0000000..c78a453 Binary files /dev/null and b/advanced/whisperx/assets/positive_example.png differ diff --git a/advanced/whisperx/audio_analysis.ipynb b/advanced/whisperx/audio_analysis.ipynb new file mode 100644 index 0000000..afb59ea --- /dev/null +++ b/advanced/whisperx/audio_analysis.ipynb @@ -0,0 +1,1324 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "8f8939f9", + "metadata": {}, + "source": [ + "# Analyzing Podcasts\n", + "\n", + "What does a great podcast sound like?\n", + "\n", + "One of the many criteria is active engagements: fast exchange of speakers, creative discussions, and not minute-long, tedious talks.\n", + "\n", + "Imagine you are a podcast creator and just finished a podcast with guests. How well did I do? Wouldn't it be nice to pump the podcast audio to an AI model, and the AI model, plus some data science magic, gives a visual representation of how things go? Are guests interacting in a meaningful way? Am I distributing time right? You might want to find these out quickly.\n", + "\n", + "With the WhisperX model running on Lepton, it is easy to build applications to understand such problems easily. With each color meaning a different speaker, each row being a minute, which of the following two podcasts is more engaging, and plausibly higher quality?\n", + "\n", + "\n", + "\n", + "Let's learn from positive examples by looking at one of my favorite podcast episodes, from 99 Percent Invisible. We'll use the speech recognition model Whisper + speaker diarization algorithm to do voice recognition, produce transcripts, and produce the conversation visualization like above.\n", + "\n", + "Disclaimer: This is only an illustrative example of how voice recognition and speaker diarization work. The copyright of the episode belongs to the original authors." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9e97e79b", + "metadata": {}, + "outputs": [], + "source": [ + "# First, let's download to the current folder.\n", + "! wget https://99percentinvisible.org/episode/stuccoed-in-time/download --quiet -O stuccoed_in_time.mp3" + ] + }, + { + "cell_type": "markdown", + "id": "f7532016", + "metadata": {}, + "source": [ + "Now, we will use the whisperx example in this folder to do the work. Let's assume that you already have a lepton account and have logged in (if not, do `lep login` in your favorite commandline interface). Let's first start the whisperx model. For this, we will need a reasonably powerful gpu, like a T4." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "be9071b6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Photon \u001b[32mwhisperx\u001b[0m created.\n", + "Photon \u001b[32mwhisperx\u001b[0m pushed to workspace.\n", + "Secret created successfully: \u001b[32mHUGGING_FACE_HUB_TOKEN\u001b[0m.\n", + "Running the most recent version of \u001b[32mwhisperx\u001b[0m: whisperx-ra5b54qt\n", + "Photon launched as \u001b[32mwhisperx\u001b[0m. Use `lep deployment status -n whisperx` to check \n", + "the status.\n" + ] + } + ], + "source": [ + "!lep photon create -n whisperx -m whisperx_background_job.py\n", + "!lep photon push -n whisperx\n", + "!lep secret create -n HUGGING_FACE_HUB_TOKEN -v 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\n", + "!lep photon run -n whisperx -dn whisperx --resource-shape gpu.t4 --secret HUGGING_FACE_HUB_TOKEN" + ] + }, + { + "cell_type": "markdown", + "id": "5006e9ce", + "metadata": {}, + "source": [ + "Let's check if the deployment has started. We can use the CLI to do so. Run this a few times till the status shows \"Running\". You can also use the Web UI url to do so." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "13d65ff6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Created at: 2023-08-21 23:41:01\n", + "Photon ID: whisperx-ra5b54qt\n", + "State: \u001b[32mRunning\u001b[0m\n", + "Web UI: \n", + "https://dashboard.lepton.ai/workspace/stable/deployments/detail/whisperx/demo\n", + "Is Public: No\n", + "Replicas List:\n", + "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┓\n", + "┃\u001b[1m \u001b[0m\u001b[1mreplica id \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mstatus\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mmessage\u001b[0m\u001b[1m \u001b[0m┃\n", + "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━┩\n", + "│ whisperx-6c9c5f786c-ppjcl │ \u001b[32mReady\u001b[0m │ (empty) │\n", + "└───────────────────────────┴────────┴─────────┘\n", + "\u001b[32m1\u001b[0m out of 1 replicas ready.\n" + ] + } + ], + "source": [ + "!lep deployment status -n whisperx" + ] + }, + { + "cell_type": "markdown", + "id": "0a75a88e", + "metadata": {}, + "source": [ + "Now that the remote service has started, let's run our local data analytics. You don't need to have a beefy GPU - that is the beautiful part. The GPU lives in the cloud.\n", + "\n", + "Let's first inspect the main function that we are going to use - `run_upload` - that uploads our audio file to the cloud and processes the work." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6e600086", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Exposed paths from the client are:\n", + "['/run', '/run_upload', '/status', '/get_result', '/queue_length']\n", + "Documentation for run_upload is:\n", + "Help on function run_upload in module leptonai.client:\n", + "\n", + "run_upload(*args, **kwargs)\n", + " Runs transcription, alignment, and diarization for the input.\n", + " \n", + " Everything is the same as the `/run` path, except that the input is uploaded\n", + " as a file. If you are using the lepton python client, you can achieve so by\n", + " from leptonai.photon import FileParam\n", + " from leptonai.client import Client\n", + " client = Client(PUT_YOUR_SERVER_INFO_HERE)\n", + " client.run_upload(upload_file=FileParam(open(\"path/to/your/file.wav\", \"rb\")))\n", + " \n", + " For more details, refer to `/run`.\n", + " \n", + " Automatically inferred parameters from openapi:\n", + " \n", + " Input Schema (*=required):\n", + " upload_file*: Any\n", + " batch_size: int (default: 4)\n", + " min_speakers: (int | None)\n", + " max_speakers: (int | None)\n", + " \n", + " Example input:\n", + " upload_file: (please use python) FileParam(open('path/to/your/file.wav', 'rb'))\n", + " \n", + " \n", + " Output Schema:\n", + " output: object\n", + "\n" + ] + } + ], + "source": [ + "from leptonai.client import Client\n", + "from leptonai.photon import FileParam\n", + "\n", + "c = Client(\"stable\", \"whisperx\", token=\"8ee43d8a2aa24f3083336ac96bd12afb\")\n", + "print(\"Exposed paths from the client are:\")\n", + "print(list(c.paths()))\n", + "print(\"Documentation for run_upload is:\")\n", + "help(c.run_upload)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "04edf9c3", + "metadata": {}, + "outputs": [], + "source": [ + "# Let's run the task, and then I'll explain.\n", + "task_id = c.run_upload(upload_file=FileParam(open(\"stuccoed_in_time.mp3\", \"rb\")))" + ] + }, + { + "cell_type": "markdown", + "id": "ad559a1e-9e67-4ff8-bb72-6356a5bcbf40", + "metadata": {}, + "source": [ + "Basically, when we are running large recognition tasks, because it will wait for quite some time to finish, it's better to not have the underlying http service long-waiting - which blocks - and it's better to finish the file upload, return a task id, and then the client side can regularly check back to see if the task finished. This is exactly how our WhisperX background-task mode server is build. You can refer to the code for more details.\n", + "\n", + "Let's inspect the task id, which is a simple UUID:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "19951c30-9d5d-485b-bae6-5e32b42cba11", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'task_id': '41ba293e-a1cf-46d7-86b3-89aeabc884c4'}\n" + ] + } + ], + "source": [ + "print(task_id)" + ] + }, + { + "cell_type": "markdown", + "id": "9e02fd8f-7fcf-4072-837a-424b8fc3680a", + "metadata": {}, + "source": [ + "Let's implement a simple waiting strategy: call `status`, and if the status is not ready, wait for progressively long time until the status says \"OK\"." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8292c64e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'status': 'ok'}\n" + ] + } + ], + "source": [ + "import time\n", + "\n", + "wait_time = 1 # in seconds\n", + "while c.status(**task_id)['status'] != \"ok\":\n", + " time.sleep(wait_time)\n", + " wait_time *= 2\n", + " if wait_time > 60 * 20:\n", + " # If the wait time is larger than 20 minutes, something is wrong.\n", + " print(\"Hmm. Something is wrong.\")\n", + " break\n", + "else:\n", + " print(c.status(**task_id))\n", + " result = c.get_result(**task_id)" + ] + }, + { + "cell_type": "markdown", + "id": "dff8b3c1-5fbd-4c1e-99c6-bc65d3205480", + "metadata": {}, + "source": [ + "It's a near hour long audio, patience is a virtue, but we'll get the results." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "7e4d855b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of speakers: 12\n" + ] + } + ], + "source": [ + "num_speakers = len(set([r[\"speaker\"] for r in result]))\n", + "print(f\"Number of speakers: {num_speakers}\")" + ] + }, + { + "cell_type": "markdown", + "id": "a17bf852-19b3-4bd9-b82c-aff82fb6bb31", + "metadata": {}, + "source": [ + "Let's print the conversations to take a look." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "4d5a45ad", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SPEAKER_03 (0'0\"-0'2\"): This is 99% Invisible.\n", + "SPEAKER_03 (0'2\"-0'5\"): I'm Roman Mars.\n", + "SPEAKER_03 (0'5\"-0'18\"): Back in the early 2000s, an architect named Trey Jordan wrote a letter to Santa Fe, New Mexico's Historic Preservation Division, laying out the details of a house he was hoping to build in the city's historic district.\n", + "SPEAKER_03 (0'18\"-0'20\"): The process started out pretty normal.\n", + "SPEAKER_02 (0'20\"-0'24\"): We were just not ready for what happened.\n", + "SPEAKER_02 (0'24\"-0'28\"): I mean, I don't remember the process being that thorny.\n", + "SPEAKER_03 (0'28\"-0'35\"): The first indication that things maybe wouldn't go smoothly had to do with the color of the stucco that Trey wanted to use.\n", + "SPEAKER_02 (0'35\"-0'37\"): I do recall that in my proposal letter,\n", + "SPEAKER_02 (0'38\"-0'51\"): I had mentioned that the stucco color would be a custom color similar to, I think it was cottonwood, which is its standard color of a commercially available stucco.\n", + "SPEAKER_07 (0'51\"-0'59\"): Buildings in the Historic District have to follow a number of design guidelines so that they fit in with Santa Fe's traditional Adobe look.\n", + "SPEAKER_03 (0'59\"-1'0\"): Senior producer Delaney Hall.\n", + "SPEAKER_07 (1'1\"-1'8\"): The style, called Pueblo Revival, comes from indigenous Pueblo architecture and the area's old Spanish missions.\n", + "SPEAKER_07 (1'8\"-1'12\"): Think low-brown buildings with smooth edges.\n", + "SPEAKER_07 (1'12\"-1'22\"): In the historic district, buildings can only be so tall, windows have to be a certain distance from the corners, roofs generally have to be flat, and stuccoes have to be earth tone.\n", + "SPEAKER_07 (1'23\"-1'30\"): And the stucco Trey wanted to use, the color that was close to cottonwood, it was an earth tone.\n", + "SPEAKER_07 (1'30\"-1'32\"): It was just a little different than usual.\n", + "SPEAKER_07 (1'32\"-1'35\"): Still, the board approved it.\n", + "SPEAKER_07 (1'35\"-1'37\"): But then things started to get weird.\n", + "SPEAKER_02 (1'37\"-1'42\"): When we stuccoed the house, it got back to me that two of the board members\n", + "SPEAKER_02 (1'43\"-1'52\"): were very upset about the color, and they took samples of cottonwood over to the house to hold it up to the stucco.\n", + "SPEAKER_02 (1'52\"-2'0\"): Well, of course, it didn't match cottonwood, but as I said in my letter, it would be a custom color similar to, and I think it was quite obvious that it was.\n", + "SPEAKER_07 (2'0\"-2'6\"): There were other subtle ways that the house was different from the traditional Santa Fe look.\n", + "SPEAKER_07 (2'6\"-2'7\"): The corners, for instance.\n", + "SPEAKER_02 (2'7\"-2'17\"): So the corners were sharp, not round, not the ooey-gooey Pueblo Revival look, but a little more crisp than that, geometric.\n", + "SPEAKER_07 (2'17\"-2'21\"): I've seen this house and it's a bit modern, a bit angular.\n", + "SPEAKER_07 (2'21\"-2'28\"): But honestly, it is not wildly different from the surrounding homes, which are done in a more traditional style.\n", + "SPEAKER_07 (2'28\"-2'37\"): And even with the bumps in the process, like the disagreement about the stucco, Trey just wasn't expecting what happened next.\n", + "SPEAKER_07 (2'37\"-2'41\"): A few weeks after his clients had moved in, Trey got a call from them.\n", + "SPEAKER_07 (2'41\"-2'44\"): The house had been defaced in the middle of the night.\n", + "SPEAKER_02 (2'44\"-2'58\"): You know, it was really, really frightening and really, really shocking that someone would get so angry that they would terrorize another family by defacing their house with a swastika and writing the words Nazi architecture on it.\n", + "SPEAKER_07 (2'58\"-3'2\"): Nazi architecture had been painted on the side of the house.\n", + "SPEAKER_07 (3'2\"-3'4\"): They don't know who did it.\n", + "SPEAKER_02 (3'4\"-3'8\"): I was so just completely shocked and frankly scared.\n", + "SPEAKER_02 (3'8\"-3'10\"): You know, I was really, I just thought, what is going on?\n", + "SPEAKER_07 (3'12\"-3'15\"): Why do you think they wrote Nazi architecture?\n", + "SPEAKER_02 (3'15\"-3'20\"): You know, I don't know if they just felt it was too strong or too modern.\n", + "SPEAKER_02 (3'20\"-3'27\"): We think it was a comment about wanting to stop buildings like this from happening in the historic districts.\n", + "SPEAKER_07 (3'27\"-3'33\"): If you're not from Santa Fe, this whole incident probably strikes you as totally absurd.\n", + "SPEAKER_07 (3'33\"-3'37\"): And to be fair, even people from Santa Fe marveled at this when it went down.\n", + "SPEAKER_02 (3'38\"-3'47\"): You know, there was some period of time thereafter where people would want to drive by and see it because, of course, it became, in this unfortunate way, it became notable.\n", + "SPEAKER_02 (3'47\"-3'54\"): And it was so funny because so many people would call me and they'd just say, I don't understand what the problem is here.\n", + "SPEAKER_02 (3'54\"-3'55\"): I just don't see it.\n", + "SPEAKER_02 (3'55\"-3'56\"): I don't get it.\n", + "SPEAKER_07 (3'57\"-4'0\"): I love the Pueblo Revival style.\n", + "SPEAKER_07 (4'0\"-4'4\"): It's part of what gives Santa Fe its very distinctive look.\n", + "SPEAKER_07 (4'4\"-4'8\"): It looks like no other city in the U.S., like no other city in the world.\n", + "SPEAKER_07 (4'8\"-4'10\"): And people here are proud of that.\n", + "SPEAKER_03 (4'11\"-4'16\"): But for some in the city, historic preservation is a very serious business.\n", + "SPEAKER_03 (4'16\"-4'27\"): The aesthetics of Santa Fe have been carefully crafted and preserved, and deviating from those aesthetics is seen, at least by some, as a serious offense.\n", + "SPEAKER_03 (4'27\"-4'30\"): You know, and I'm gonna call you a Nazi level of offense.\n", + "SPEAKER_07 (4'31\"-4'45\"): And this battle over style goes back more than a hundred years, ever since a group of early preservationists set out a vision for Santa Fe's architecture and, in the process, dramatically transformed the town.\n", + "SPEAKER_03 (4'47\"-4'50\"): Adobe has a long history in northern New Mexico.\n", + "SPEAKER_03 (4'50\"-4'54\"): Building with mud goes back hundreds and hundreds of years.\n", + "SPEAKER_03 (4'54\"-5'1\"): The technique was favored both by the indigenous people of the region and by the Spanish settlers who arrived later on.\n", + "SPEAKER_07 (5'1\"-5'9\"): But back in the 1800s, when New Mexico was vying to become a state, Santa Fe actually tried to leave its mud-based architecture behind.\n", + "SPEAKER_07 (5'10\"-5'15\"): The city constructed buildings that screamed, hey, we're just like you guys.\n", + "SPEAKER_10 (5'15\"-5'18\"): They were Italianate business blocks on the plaza.\n", + "SPEAKER_07 (5'18\"-5'20\"): Architectural historian Chris Wilson.\n", + "SPEAKER_10 (5'21\"-5'32\"): schools and kind of a red brick Romanesque style, a 1900 neoclassical capital that would have been at home in any of the other new states.\n", + "SPEAKER_03 (5'32\"-5'39\"): Local leaders hoped this architectural posturing would help convince Congress to let New Mexico into the Union.\n", + "SPEAKER_03 (5'39\"-5'44\"): They were well aware that East Coasters viewed them with some suspicion.\n", + "SPEAKER_03 (5'44\"-5'50\"): The territory seemed like a dusty foreign outpost, unlikely to integrate into mainstream American culture.\n", + "SPEAKER_07 (5'51\"-5'59\"): Eventually, in 1912, after more than 60 years of trying, New Mexico became a state.\n", + "SPEAKER_07 (5'59\"-6'2\"): But all of these attempts to fit in, they ended up being a bad thing.\n", + "SPEAKER_07 (6'2\"-6'6\"): Especially for New Mexico's newly minted capital, Santa Fe.\n", + "SPEAKER_03 (6'6\"-6'9\"): Santa Fe was struggling economically.\n", + "SPEAKER_03 (6'9\"-6'22\"): There was a railroad that went through New Mexico, but despite being called the Santa Fe Railroad, it didn't go directly through Santa Fe, and the city couldn't develop any serious industries without good rail access.\n", + "SPEAKER_07 (6'22\"-6'31\"): Santa Fe was rapidly shrinking, and so the mayor at the time put together a planning board and told them to come up with a plan to save the city.\n", + "SPEAKER_07 (6'32\"-6'34\"): they landed on tourism.\n", + "SPEAKER_07 (6'34\"-6'42\"): Tourists had already started to come to Santa Fe in small numbers, but the board noticed that when they arrived, they weren't that impressed.\n", + "SPEAKER_10 (6'42\"-6'49\"): Once they see our Americanized city, they press on, they press north to the Pueblos.\n", + "SPEAKER_10 (6'49\"-6'57\"): Tourism can be our salvation, but only if we reverse the ill-conceived Americanization of the last three decades.\n", + "SPEAKER_07 (6'57\"-7'2\"): The board wrote up a document that's become known as the 1912 plan.\n", + "SPEAKER_07 (7'2\"-7'8\"): They recommended the city preserve its traditional Adobe architecture, but the plan went even further.\n", + "SPEAKER_07 (7'8\"-7'14\"): It said that any new development should also be done in the Santa Fe style.\n", + "SPEAKER_07 (7'14\"-7'20\"): They wanted to create a kind of citywide architectural brand based on the historical precedent.\n", + "SPEAKER_03 (7'20\"-7'25\"): The sweeping scope of the 1912 plan was pretty radical.\n", + "SPEAKER_03 (7'25\"-7'28\"): At the time, most historic preservation in the U.S.\n", + "SPEAKER_03 (7'28\"-7'31\"): focused on the homes of important old white guys.\n", + "SPEAKER_10 (7'31\"-7'33\"): Mount Vernon, Monticello.\n", + "SPEAKER_10 (7'33\"-7'36\"): So preservation was focused on single buildings.\n", + "SPEAKER_03 (7'36\"-7'46\"): Santa Fe, on the other hand, decided to focus on the everyday architecture of its ordinary people, and it expanded preservation beyond single buildings to the entire community.\n", + "SPEAKER_03 (7'46\"-7'49\"): A city had never tried something so far-reaching.\n", + "SPEAKER_07 (7'49\"-7'55\"): But many of the leaders behind the effort believed that this could be Santa Fe's salvation.\n", + "SPEAKER_07 (7'55\"-8'4\"): Not in pretending to be a conventional American city, but in embracing its difference and selling it to outsiders.\n", + "SPEAKER_00 (8'4\"-8'12\"): To those who are devotees of the great outdoors, to the splendors of its vastness and magnificent scenery, the urge is west to the Indian country.\n", + "SPEAKER_07 (8'13\"-8'15\"): Santa Fe's tourism campaign took off.\n", + "SPEAKER_07 (8'15\"-8'21\"): By the 19-teens, a wave of mostly white newcomers began arriving in the state.\n", + "SPEAKER_07 (8'21\"-8'25\"): They were artists and anthropologists and health seekers.\n", + "SPEAKER_07 (8'25\"-8'34\"): Chris Wilson calls them internal expats, the kind of people who might have gone to Paris, but instead went to Santa Fe.\n", + "SPEAKER_03 (8'34\"-8'36\"): And one of those newcomers was John Gaw Meem.\n", + "SPEAKER_11 (8'36\"-8'42\"): I became particularly aware of New Mexican architecture while lying in bed.\n", + "SPEAKER_07 (8'43\"-8'50\"): John Gaw Meem was a civil engineer who'd come to Santa Fe from New York to recover from tuberculosis.\n", + "SPEAKER_07 (8'50\"-8'55\"): And while he was recuperating, he became enthralled with the architecture.\n", + "SPEAKER_11 (8'55\"-9'4\"): And I decided then and there, even though I was, I thought, getting very advanced in years, I'd better change my profession.\n", + "SPEAKER_11 (9'4\"-9'6\"): And what I really wanted to be was an architect.\n", + "SPEAKER_03 (9'7\"-9'19\"): And so at the very advanced age of 27, Meem switched careers and quickly became Santa Fe's go-to architect, especially for wealthy transplants from the East Coast and Midwest.\n", + "SPEAKER_10 (9'19\"-9'25\"): But also then of important public buildings, churches, county courthouse, and so forth.\n", + "SPEAKER_07 (9'25\"-9'33\"): Meem became the leading architect of the Santa Fe style, and he helped to bring a very old building tradition into the modern era.\n", + "SPEAKER_07 (9'34\"-9'37\"): he didn't always use actual mud bricks.\n", + "SPEAKER_07 (9'37\"-9'44\"): He used reinforced concrete and steel to create an adobe-ish take on that old style.\n", + "SPEAKER_03 (9'44\"-9'51\"): And his work helped the city of Santa Fe actually create the architectural brand it had imagined.\n", + "SPEAKER_11 (9'51\"-10'3\"): And I think it's perfectly legitimate, not only legitimate, but almost a duty in a part of the world where we have native architecture with these wonderful shapes that we should recall them.\n", + "SPEAKER_11 (10'4\"-10'5\"): It's worth preserving.\n", + "SPEAKER_11 (10'5\"-10'9\"): I certainly agree with you 100% on that, as you know.\n", + "SPEAKER_07 (10'9\"-10'13\"): All over town, new buildings went up in this adobe style.\n", + "SPEAKER_07 (10'13\"-10'16\"): And as far as attracting tourists, it worked.\n", + "SPEAKER_07 (10'16\"-10'22\"): Between 1920 and 1930, Santa Fe went from 200 hotel rooms to 600.\n", + "SPEAKER_03 (10'22\"-10'29\"): Everything was going great until a pesky new form of architecture showed up on the scene, threatening to ruin everything.\n", + "SPEAKER_07 (10'30\"-10'35\"): In the 1950s, architectural modernism was spreading, even in Santa Fe.\n", + "SPEAKER_07 (10'35\"-10'45\"): The city was growing, the tourist industry was driving more development, and there was a sense that Santa Fe was losing its grip on the style that had made it so distinct.\n", + "SPEAKER_10 (10'45\"-10'55\"): And the traditionalist community that had reached this consensus around the revival style becomes alarmed, and they react against it.\n", + "SPEAKER_03 (10'55\"-10'59\"): And so the preservationists, with John Gaumeme as one of their leaders, doubled down.\n", + "SPEAKER_03 (11'0\"-11'5\"): In 1957, the city passed an ordinance that required the Santa Fe style.\n", + "SPEAKER_03 (11'5\"-11'14\"): It elaborated a number of sub-styles and created a large historic district in the center of the city, which included some of Santa Fe's oldest neighborhoods.\n", + "SPEAKER_03 (11'14\"-11'16\"): They were full of Hispanic families.\n", + "SPEAKER_03 (11'16\"-11'20\"): Some of them had lived for generations in adobe homes built by their ancestors.\n", + "SPEAKER_07 (11'21\"-11'28\"): With this new ordinance, any changes to a building in the district now had to be approved by a design board.\n", + "SPEAKER_07 (11'28\"-11'32\"): And at first, critics worried mostly about aesthetics.\n", + "SPEAKER_07 (11'32\"-11'40\"): They thought the look of the city would become boring and homogenous, or that it would turn into a kind of hokey Old West stage set.\n", + "SPEAKER_10 (11'40\"-11'51\"): They weren't against the city having a distinctive character, but they just doubted that the style guidelines were going to do it in the most vibrant living way.\n", + "SPEAKER_07 (11'51\"-11'57\"): And were there questions raised about what the ordinance might do to affordability in the central city?\n", + "SPEAKER_10 (11'57\"-12'4\"): No, there weren't arguments about, you know, potential gentrification, as we would call it now.\n", + "SPEAKER_01 (12'4\"-12'12\"): Finally tonight, the sound of moving that roar you hear in the American Southwest these days is the traffic heading to Santa Fe, New Mexico.\n", + "SPEAKER_01 (12'12\"-12'15\"): The population is up 12 percent over the past decade.\n", + "SPEAKER_07 (12'15\"-12'21\"): Over the next couple decades, Santa Fe got hit with a huge wave of tourism and resettlement.\n", + "SPEAKER_07 (12'21\"-12'29\"): In the 1970s, there was an oil boom in neighboring Texas, and a bunch of newly rich Texans moved to Santa Fe.\n", + "SPEAKER_03 (12'29\"-12'37\"): Then in the 1980s, as international travel became more of a thing, Santa Fe became not just a national destination, but an international one.\n", + "SPEAKER_03 (12'37\"-12'43\"): The city had spent decades perfecting its tourist identity, figuring out how to package and sell itself.\n", + "SPEAKER_03 (12'43\"-12'45\"): Maybe too effectively.\n", + "SPEAKER_10 (12'45\"-12'56\"): The readers of Condé Nast's travel magazine in the early 1980s bought Santa Fe their number one tourist destination, not just in the United States, but in the world.\n", + "SPEAKER_03 (12'57\"-13'0\"): A million, sometimes two million tourists started coming every year.\n", + "SPEAKER_03 (13'0\"-13'4\"): This was in a town of 50 or 60,000 residents.\n", + "SPEAKER_03 (13'4\"-13'7\"): Santa Fe started to get totally overrun by these visitors.\n", + "SPEAKER_07 (13'7\"-13'12\"): And some of these visitors decided to buy up more of the city's old historic homes.\n", + "SPEAKER_07 (13'12\"-13'16\"): This was gentrification, but, like, on steroids.\n", + "SPEAKER_10 (13'16\"-13'25\"): These are the 1% or the one-tenth of 1%, the very wealthiest of people, who start to have multiple homes.\n", + "SPEAKER_10 (13'25\"-13'34\"): They have a pied-à-terre in Manhattan, and they've got a house in Nantucket, and maybe a pied-à-terre in Paris, and now they want to have a house in Santa Fe.\n", + "SPEAKER_04 (13'35\"-13'40\"): In Santa Fe, the neighborhoods are changing as fast as the builders can put up new buildings.\n", + "SPEAKER_04 (13'40\"-13'42\"): There aren't a lot of barrios left.\n", + "SPEAKER_04 (13'42\"-13'45\"): They're all becoming playgrounds for the rich.\n", + "SPEAKER_04 (13'45\"-13'50\"): For the first time since 1600, there are now more Anglos here than there are Hispanics.\n", + "SPEAKER_07 (13'50\"-13'57\"): It was during the 90s that Trey Jordan, the architect, started working for an architecture firm in Santa Fe.\n", + "SPEAKER_07 (13'57\"-14'0\"): And he loved learning to build in the Santa Fe style.\n", + "SPEAKER_02 (14'1\"-14'5\"): It's a vernacular that I think a lot of people find it easy to like.\n", + "SPEAKER_02 (14'5\"-14'8\"): I mean, there's something quite charming about it.\n", + "SPEAKER_07 (14'8\"-14'12\"): But he could also understand the irony of what was happening.\n", + "SPEAKER_07 (14'12\"-14'17\"): How this old tradition had become in vogue with Santa Fe's wealthy newcomers.\n", + "SPEAKER_02 (14'17\"-14'22\"): It's more or less a vernacular of poverty and a vernacular of survival.\n", + "SPEAKER_02 (14'23\"-14'33\"): And we spend extraordinary amounts of money to nowadays reproduce a style that was really, you know, born out of necessity.\n", + "SPEAKER_07 (14'34\"-14'39\"): Over time, the city implemented more restrictions and more code.\n", + "SPEAKER_07 (14'39\"-14'41\"): The historic districts expanded.\n", + "SPEAKER_07 (14'41\"-14'44\"): Limits were placed on the height of buildings.\n", + "SPEAKER_07 (14'44\"-14'48\"): Commercial districts were encouraged to adopt the Adobe look.\n", + "SPEAKER_07 (14'48\"-14'54\"): And so Santa Fe began to have stuff like a fake Adobe iHop and a fake Adobe Panda Express.\n", + "SPEAKER_07 (14'54\"-14'59\"): A wave of brown stucco washed over the city.\n", + "SPEAKER_07 (14'59\"-15'2\"): The 80s and 90s were a tough time for a lot of people in Santa Fe.\n", + "SPEAKER_07 (15'3\"-15'12\"): I asked one old-timer, Joseph Montoya, what it was like living here during those years, and he thought for a couple moments before saying, it sucked.\n", + "SPEAKER_06 (15'12\"-15'23\"): I think what happened, whether it was appropriate or not, a building resentment over like, gosh, we've got a lot of fine restaurants now in town that we didn't have before, right?\n", + "SPEAKER_06 (15'23\"-15'24\"): I can't eat in them.\n", + "SPEAKER_07 (15'24\"-15'28\"): Joseph's family connection to Santa Fe goes back generations.\n", + "SPEAKER_06 (15'29\"-15'31\"): I don't go to the plaza because it's no longer my plaza.\n", + "SPEAKER_06 (15'31\"-15'34\"): I don't feel comfortable in my own town.\n", + "SPEAKER_07 (15'34\"-15'37\"): Joseph joined the city government in 1990.\n", + "SPEAKER_07 (15'37\"-15'41\"): He's now the executive director of the County Housing Authority.\n", + "SPEAKER_07 (15'41\"-15'45\"): Back then, he was also working on community development and housing issues.\n", + "SPEAKER_07 (15'45\"-15'53\"): And the first thing he did was review some studies the city had already done, trying to understand why locals couldn't afford to live here anymore.\n", + "SPEAKER_03 (15'54\"-16'4\"): He says that there was even one study that tried to actually quantify the cost of the Santa Fe style, like the exposed wood beams that support the ceilings in many homes.\n", + "SPEAKER_06 (16'4\"-16'6\"): How much do vehicles cost?\n", + "SPEAKER_06 (16'6\"-16'12\"): Is there a cost difference between the kind of windows you have to put in or not, or different doors?\n", + "SPEAKER_06 (16'12\"-16'17\"): And they tried to add up that cost over and above what you might have to pay anyway.\n", + "SPEAKER_03 (16'17\"-16'24\"): And yeah, the carved wood beams and the ornamental corbeling, for example, did add some costs, but that wasn't really the central issue.\n", + "SPEAKER_03 (16'24\"-16'32\"): More relevant was the number of wealthy buyers flooding the city and driving up the cost of everything, including land.\n", + "SPEAKER_03 (16'32\"-16'38\"): The city just couldn't build enough subsidized housing to keep lower-income people housed.\n", + "SPEAKER_07 (16'38\"-16'43\"): And that was partly because some of those newcomers began to fight new construction.\n", + "SPEAKER_07 (16'43\"-16'47\"): Not just in the historic district, but across the city.\n", + "SPEAKER_07 (16'47\"-16'51\"): Joseph talks about the arguments they would make at community meetings.\n", + "SPEAKER_07 (16'51\"-16'56\"): They would speak out against more density, more infill housing, taller buildings.\n", + "SPEAKER_06 (16'56\"-17'0\"): They would say, This is going to ruin the quality of my life.\n", + "SPEAKER_06 (17'0\"-17'6\"): I bought here expecting it to always stay the same because the community character is important to me.\n", + "SPEAKER_06 (17'7\"-17'10\"): And it was seen as you were being a good citizen, right?\n", + "SPEAKER_06 (17'10\"-17'13\"): And, you know, I think that's something that worked for a lot of people, right?\n", + "SPEAKER_06 (17'13\"-17'18\"): That, oh yeah, development is what ruined this city, and now we're going to stop it.\n", + "SPEAKER_07 (17'18\"-17'22\"): But all the talk about community character always frustrated Joseph.\n", + "SPEAKER_07 (17'22\"-17'25\"): Because what community were they talking about?\n", + "SPEAKER_07 (17'25\"-17'26\"): And what character?\n", + "SPEAKER_06 (17'26\"-17'26\"): So it's like,\n", + "SPEAKER_06 (17'27\"-17'30\"): My God, you know, I know exactly that place they're talking about.\n", + "SPEAKER_06 (17'30\"-17'33\"): We used to hunt rabbits there.\n", + "SPEAKER_06 (17'33\"-17'35\"): And so that was the community character back then.\n", + "SPEAKER_06 (17'35\"-17'40\"): And previous to that, that was a Native American campground.\n", + "SPEAKER_06 (17'40\"-17'42\"): So what character are we taking?\n", + "SPEAKER_06 (17'42\"-17'46\"): You know, the character that was created in 1973.\n", + "SPEAKER_07 (17'46\"-17'51\"): Joseph watched in dismay as the Nimbys gained political power and influence.\n", + "SPEAKER_06 (17'52\"-18'4\"): I felt that if we've gotten to the point where there's a majority of people that the politicians were listening to that can make these arguments and win, the city has been lost.\n", + "SPEAKER_06 (18'4\"-18'15\"): It was sad to see the demise, the complete demise of families and history and legacy being washed away.\n", + "SPEAKER_03 (18'20\"-18'23\"): In some ways, Santa Fe had become a victim of its own success.\n", + "SPEAKER_03 (18'23\"-18'33\"): The early preservationists set out a vision for protecting Santa Fe's historic look, and they helped create a tourism industry that's still the foundation of the city's economy.\n", + "SPEAKER_03 (18'33\"-18'37\"): But the popularity of Santa Fe has also helped to create serious inequality.\n", + "SPEAKER_03 (18'37\"-18'47\"): The town became an increasingly expensive place to live, and lots of people work in hospitality, taking care of tourists and making service economy wages.\n", + "SPEAKER_07 (18'47\"-18'52\"): Locals who were pushed out of the historic district moved to the more affordable south side.\n", + "SPEAKER_07 (18'52\"-18'55\"): Now many of them can't even afford to live there.\n", + "SPEAKER_07 (18'55\"-19'1\"): Of the 80 cousins Joseph grew up with, he says only five are still in the city.\n", + "SPEAKER_07 (19'1\"-19'7\"): These days, more than half of the people who work in Santa Fe don't live here, including Joseph.\n", + "SPEAKER_07 (19'7\"-19'13\"): He lives in Albuquerque, commuting from an hour away to fight for affordable housing in his old hometown.\n", + "SPEAKER_07 (19'17\"-19'30\"): Up until recently, I lived on the historic east side of Santa Fe, in a blocky and frankly unattractive yellow stucco house surrounded by gorgeous multi-million dollar adobe homes.\n", + "SPEAKER_07 (19'30\"-19'33\"): And it was a strange place to live.\n", + "SPEAKER_07 (19'33\"-19'44\"): I would sometimes find myself walking through the neighborhood as evening approached and the sky got dark, and I was always struck by the number of homes in which the lights just never came on.\n", + "SPEAKER_07 (19'45\"-19'48\"): The neighborhood was eerily quiet.\n", + "SPEAKER_07 (19'48\"-19'52\"): Down the street from me, there was an old adobe house that no one seemed to live in.\n", + "SPEAKER_07 (19'52\"-19'54\"): There was never a car in the driveway.\n", + "SPEAKER_07 (19'54\"-19'57\"): I literally never saw someone come or go.\n", + "SPEAKER_07 (19'57\"-20'3\"): But landscapers would come in a couple times a month to mow the lawn and trim the trees.\n", + "SPEAKER_07 (20'3\"-20'7\"): It was a beautifully maintained, seemingly empty specimen.\n", + "SPEAKER_08 (20'8\"-20'20\"): We've been very intent on preserving the architectural character of our historic districts, but what has fallen through the cracks has been the community character and how that has really changed.\n", + "SPEAKER_07 (20'20\"-20'22\"): This is Lisa Gavioli-Roach.\n", + "SPEAKER_07 (20'22\"-20'32\"): She first worked in the Historic Preservation Division as a senior planner, and she said it often felt like they managed the districts as if the buildings were works of art in a museum.\n", + "SPEAKER_07 (20'33\"-20'39\"): There was little discussion, she said, of the people who actually lived in those neighborhoods.\n", + "SPEAKER_07 (20'39\"-20'42\"): She started to question everything about her field.\n", + "SPEAKER_07 (20'42\"-20'49\"): And then she became the head of the division, which put her in a position to try and make some changes.\n", + "SPEAKER_03 (20'49\"-20'55\"): Now Lisa says it's a mistake for preservationists to focus exclusively on the built environment of a neighborhood.\n", + "SPEAKER_03 (20'55\"-20'57\"): Neighborhoods aren't just a collection of buildings.\n", + "SPEAKER_08 (20'58\"-21'0\"): It's not just visual character that you're looking at.\n", + "SPEAKER_08 (21'0\"-21'6\"): It's the sounds that you hear, the smells that you smell, the people that you interact with.\n", + "SPEAKER_08 (21'6\"-21'8\"): All of those things contribute to a community's character.\n", + "SPEAKER_07 (21'9\"-21'16\"): And those things have been dramatically altered in the historic neighborhoods of Santa Fe over the past few decades.\n", + "SPEAKER_07 (21'16\"-21'21\"): You don't often hear kids playing or see neighbors talking to each other over a fence.\n", + "SPEAKER_08 (21'21\"-21'28\"): You're seeing tourists taking photos and you yourself start to feel like you're just like a character in a diorama or something.\n", + "SPEAKER_08 (21'28\"-21'31\"): You know, it starts to feel very different.\n", + "SPEAKER_03 (21'31\"-21'35\"): The transformation of Santa Fe's old neighborhoods is complex.\n", + "SPEAKER_03 (21'35\"-21'40\"): It's not like historic preservation is entirely at fault, but Lisa does think it's played a role.\n", + "SPEAKER_08 (21'41\"-21'47\"): The city's approach to preservation is highly prescriptive, down to every single detail.\n", + "SPEAKER_08 (21'47\"-21'59\"): Any exterior change has to come through our office, and most of them need a permit, even if you're fixing your fence or repainting your windows or, you know, little minor things like that.\n", + "SPEAKER_08 (21'59\"-22'2\"): It feels very invasive, I think, for many people.\n", + "SPEAKER_07 (22'3\"-22'5\"): And the process is also expensive.\n", + "SPEAKER_07 (22'5\"-22'8\"): It often requires hiring an architect.\n", + "SPEAKER_07 (22'8\"-22'13\"): It's just one more thing that can make it hard for old-timers to stay in their homes.\n", + "SPEAKER_08 (22'13\"-22'21\"): You know, I was speaking to a homeowner just last week who was talking to me about her experience renovating her grandfather's home.\n", + "SPEAKER_08 (22'21\"-22'27\"): And she just said the whole time that she was going through it, she really felt like it was tearing her family apart.\n", + "SPEAKER_08 (22'27\"-22'30\"): And she just wondered, what are we preserving?\n", + "SPEAKER_08 (22'30\"-22'32\"): She just kept saying that, what are we preserving?\n", + "SPEAKER_08 (22'33\"-22'41\"): because certainly my family's not being preserved, my family's connection to this place is not being respected, and it's so arduous just to get through it.\n", + "SPEAKER_03 (22'41\"-22'51\"): Over the past eight months or so, the Historic Division has been working on a study to quantify the changes that have happened in the city's historic districts over the years.\n", + "SPEAKER_03 (22'51\"-22'58\"): They've found that between 1980 and 2018, even as the population of Santa Fe grew, the historic districts emptied out.\n", + "SPEAKER_07 (22'59\"-23'5\"): Old families left, and their homes turned into second homes or short-term rentals.\n", + "SPEAKER_07 (23'5\"-23'11\"): The people who now live in the historic district are generally white, wealthy, and old.\n", + "SPEAKER_08 (23'11\"-23'15\"): The gentrification of our historic neighborhoods is all but complete.\n", + "SPEAKER_08 (23'15\"-23'18\"): And in many ways, it's not reversible.\n", + "SPEAKER_08 (23'18\"-23'27\"): And I think instead of just singularly celebrating historic preservation for creating and maintaining this tourist economy,\n", + "SPEAKER_08 (23'28\"-23'37\"): We have to recognize that there have been other experiences here as well and that the outcomes for our community are not all good.\n", + "SPEAKER_08 (23'37\"-23'38\"): Is this really what we want?\n", + "SPEAKER_08 (23'38\"-23'41\"): What do we value now in our community?\n", + "SPEAKER_08 (23'41\"-23'43\"): It's not 1957 anymore.\n", + "SPEAKER_08 (23'43\"-23'47\"): It's not 1912 anymore.\n", + "SPEAKER_07 (23'47\"-23'57\"): There was one person I met while working on this story who embodied the complicated and sometimes contradictory relationship that Santa Fe has to its own past.\n", + "SPEAKER_07 (23'58\"-24'4\"): Like Joseph, Ray Herrera's family has lived in Santa Fe for many generations.\n", + "SPEAKER_07 (24'4\"-24'9\"): Ray grew up building and maintaining his family's old adobe homes.\n", + "SPEAKER_09 (24'9\"-24'11\"): Everybody built with adobe back then.\n", + "SPEAKER_09 (24'11\"-24'13\"): I guess you could say it's in your blood.\n", + "SPEAKER_09 (24'13\"-24'21\"): If you're a local Hispanic like me, whose parents and grandparents and great-grandparents were from Santa Fe, you know, originally,\n", + "SPEAKER_07 (24'22\"-24'25\"): Ray still lives in the Historic District.\n", + "SPEAKER_07 (24'25\"-24'34\"): His family is one of the few remaining so-called legacy families, and he's watched as many of his neighbors and friends have been forced to leave.\n", + "SPEAKER_07 (24'34\"-24'38\"): But he still supports the work of Historic Preservation.\n", + "SPEAKER_07 (24'38\"-24'40\"): In fact, he's extremely committed to it.\n", + "SPEAKER_09 (24'41\"-24'44\"): I was there at every meeting for 20-some years.\n", + "SPEAKER_07 (24'44\"-24'48\"): Every week, Ray would show up at the H-Board meetings to testify.\n", + "SPEAKER_07 (24'48\"-24'58\"): He would remind new homeowners about the history of the neighborhood, about who used to live in their houses, and about what Santa Fe used to be like.\n", + "SPEAKER_09 (24'58\"-25'3\"): The buildings speak for the people that were here a hundred years ago.\n", + "SPEAKER_07 (25'4\"-25'9\"): Ray says his family and friends don't really understand his interest in preservation.\n", + "SPEAKER_07 (25'9\"-25'18\"): For many of them, the historic districts and the whole project of preservation seems to be entirely in the interest of white homeowners.\n", + "SPEAKER_09 (25'18\"-25'29\"): And my relatives and friends that don't live here anymore, they tell me, why do you spend your time fighting for the Anglos?\n", + "SPEAKER_09 (25'31\"-25'34\"): And I said, I'm not fighting for the Anglos.\n", + "SPEAKER_09 (25'34\"-25'41\"): I'm fighting to protect the small town feeling of Santa Fe.\n", + "SPEAKER_09 (25'41\"-25'45\"): That's what I try to preserve.\n", + "SPEAKER_09 (25'45\"-25'53\"): You know, if it were up to these home builders and developers, we'd have homes running up and down the Santa Fe River.\n", + "SPEAKER_07 (25'53\"-25'57\"): And you don't think it's worth it, even if it, say,\n", + "SPEAKER_07 (25'58\"-26'2\"): Let Hispanic people who've been here for generations be here.\n", + "SPEAKER_09 (26'2\"-26'12\"): The thing is that it's sort of too late to say that anymore because 90 percent of the Hispanic families have moved out.\n", + "SPEAKER_07 (26'15\"-26'31\"): It's almost as if, unable to preserve the actual community of his neighborhood, the people he used to know, the neighbors he grew up with, Ray now has to be content to preserve the buildings they left behind.\n", + "SPEAKER_07 (26'31\"-26'36\"): Over the years, Ray has fought every kind of development you can imagine.\n", + "SPEAKER_07 (26'36\"-26'42\"): Development in the historic district, high-end housing developments, affordable housing developments.\n", + "SPEAKER_09 (26'43\"-26'43\"): anything.\n", + "SPEAKER_09 (26'43\"-26'47\"): Rey Herrera was there fighting anything.\n", + "SPEAKER_09 (26'47\"-26'53\"): If I showed up to a meeting, everybody stopped and looked and said, Oh God, what's happening?\n", + "SPEAKER_09 (26'53\"-26'54\"): Rey Herrera is here.\n", + "SPEAKER_07 (26'55\"-27'2\"): After watching Santa Fe change so much over his lifetime, Ray now resists every change he can.\n", + "SPEAKER_07 (27'2\"-27'7\"): He's holding tight to an idea that many in Santa Fe believe deeply.\n", + "SPEAKER_07 (27'7\"-27'13\"): It's a philosophy of urban planning that could be summed up as, if we don't build it, they won't come.\n", + "SPEAKER_06 (27'13\"-27'17\"): Well, if we don't build it, we're going to stay the same.\n", + "SPEAKER_06 (27'17\"-27'18\"): And we want to stay the same.\n", + "SPEAKER_07 (27'18\"-27'19\"): Joseph Montoya again.\n", + "SPEAKER_06 (27'19\"-27'21\"): And that is simply\n", + "SPEAKER_06 (27'22\"-27'23\"): Not true, right?\n", + "SPEAKER_06 (27'23\"-27'26\"): What happens is the fittest survive, right?\n", + "SPEAKER_06 (27'26\"-27'31\"): And people eventually get priced out of their ability to stay here.\n", + "SPEAKER_06 (27'31\"-27'41\"): Change is just a part of life, and so you either accept it and try to take advantage of it, or you try to deny it and you get run over by it.\n", + "SPEAKER_03 (27'41\"-27'46\"): The early preservationists tried to freeze Santa Fe at a particular moment in time.\n", + "SPEAKER_03 (27'46\"-27'54\"): The style that they defined in 1912 and then codified in 1957, largely remains the style of the city today.\n", + "SPEAKER_11 (27'54\"-28'5\"): If this had not been done, we would have lost, I think, the kind of city that Santa Fe is right now.\n", + "SPEAKER_07 (28'5\"-28'10\"): When John Dahmeim said that, the city that Santa Fe is right now, it was 1964.\n", + "SPEAKER_07 (28'12\"-28'20\"): He and the other preservationists couldn't have predicted the changes that would sweep over the city in the decades since then.\n", + "SPEAKER_07 (28'20\"-28'29\"): But in holding on so tight to the architecture of that time, we've actually already lost a lot of the people and cultures that used to make Santa Fe what it was.\n", + "SPEAKER_07 (28'31\"-28'42\"): And people like Joseph Montoya believe that if we don't change course, if we don't allow for more development and more housing, the rest of Santa Fe will follow suit.\n", + "SPEAKER_07 (28'42\"-28'50\"): The whole city will become a kind of museum of culture's past, with only the buildings reflecting who once lived here.\n", + "SPEAKER_03 (28'55\"-29'11\"): Coming up after the break, we'll learn more about the Pueblo building traditions that form the basis for the Santa Fe style.\n", + "SPEAKER_03 (29'11\"-29'17\"): So we're back with Delaney again, and you have another story related to the Santa Fe style that you wanted to share with us.\n", + "SPEAKER_03 (29'17\"-29'18\"): So, um, so where should we start?\n", + "SPEAKER_07 (29'18\"-29'22\"): Well, I wanted to start with Roxanne Swensell.\n", + "SPEAKER_07 (29'22\"-29'26\"): She's an artist and builder from Santa Clara Pueblo.\n", + "SPEAKER_07 (29'26\"-29'36\"): And for people who aren't familiar with the pueblos here in New Mexico, they're indigenous communities that, you know, in some cases go back for millennia.\n", + "SPEAKER_07 (29'36\"-29'40\"): So they have a very longstanding connection to this place.\n", + "SPEAKER_03 (29'40\"-29'40\"): Very long.\n", + "SPEAKER_07 (29'41\"-29'49\"): Yeah, and I would say in general, Santa Fe has a pretty complicated relationship with the surrounding Pueblos.\n", + "SPEAKER_07 (29'49\"-30'0\"): You know, the city has built a tourism industry largely around indigenous art and culture, and so architecture is just one example of that.\n", + "SPEAKER_07 (30'0\"-30'5\"): And so when we talk about the Pueblo Revival style, it's right there in the name.\n", + "SPEAKER_07 (30'5\"-30'10\"): It's an interpretation or an appropriation of Pueblo design.\n", + "SPEAKER_07 (30'11\"-30'17\"): And so I was curious to talk with Roxanne about, you know, what she makes of the architecture in Santa Fe.\n", + "SPEAKER_05 (30'17\"-30'19\"): You know, there's a charming perspective.\n", + "SPEAKER_05 (30'19\"-30'25\"): I can understand somebody coming in from somewhere else and thinking, this is different.\n", + "SPEAKER_05 (30'25\"-30'26\"): This is kind of unique.\n", + "SPEAKER_05 (30'26\"-30'33\"): For us that grew up here, I find it incredibly distasteful.\n", + "SPEAKER_05 (30'33\"-30'36\"): And we joke, we call Santa Fe, Santa fake.\n", + "SPEAKER_05 (30'36\"-30'39\"): because of the fake Adobe.\n", + "SPEAKER_07 (30'39\"-30'43\"): So there were a couple of reasons I wanted to speak with Roxanne.\n", + "SPEAKER_07 (30'43\"-30'47\"): One is that she has a long history of building real Adobe houses.\n", + "SPEAKER_07 (30'47\"-30'50\"): She's built 20 over the course of her life so far.\n", + "SPEAKER_07 (30'51\"-31'6\"): And the other reason is that her mom, Rina Swentzel, wrote a lot about the disconnect between Pueblo ideas about architecture and, you know, European or I guess Western ideas about architecture.\n", + "SPEAKER_07 (31'6\"-31'13\"): And Rina died in 2015, but Roxanne told me about how she got interested in architecture in the first place.\n", + "SPEAKER_07 (31'13\"-31'18\"): And it all went back to this conflict at the Pueblo in the 1970s.\n", + "SPEAKER_07 (31'18\"-31'25\"): And what happened is that the government, HUD basically, came into Santa Clara to build new housing.\n", + "SPEAKER_05 (31'25\"-31'32\"): But the houses had nothing to do with our cultural ways of life or values.\n", + "SPEAKER_05 (31'32\"-31'34\"): But they were cheap and free.\n", + "SPEAKER_05 (31'34\"-31'38\"): So, you know, people weren't going to turn that away.\n", + "SPEAKER_05 (31'38\"-31'41\"): But my mother was desperate to see if she could stop it.\n", + "SPEAKER_03 (31'43\"-31'46\"): And so why exactly did Reno want to stop it?\n", + "SPEAKER_07 (31'46\"-31'50\"): The hud houses were basically suburban in their design.\n", + "SPEAKER_07 (31'50\"-31'54\"): You know, they were these single family homes.\n", + "SPEAKER_05 (31'54\"-32'2\"): Where it's individual thinking, you have your own yard, you keep your neighbor out, you have your prefab house that you didn't make yourself.\n", + "SPEAKER_05 (32'3\"-32'8\"): materials that you can't just go down the hill and dig up your mud and make a house.\n", + "SPEAKER_05 (32'8\"-32'12\"): You have to have money to buy the materials.\n", + "SPEAKER_05 (32'12\"-32'19\"): The way the houses were designed had to do with a lifestyle that was foreign to\n", + "SPEAKER_05 (32'19\"-32'21\"): Pueblo lifestyle.\n", + "SPEAKER_07 (32'21\"-32'28\"): And so Rina actually enrolled at the School of Architecture and Planning at UNM in Albuquerque.\n", + "SPEAKER_07 (32'28\"-32'37\"): And Roxanne said that she really felt like she couldn't fight this new HUD development without first understanding the thinking behind it.\n", + "SPEAKER_05 (32'37\"-32'37\"): So she\n", + "SPEAKER_05 (32'39\"-32'47\"): was very highly educated for that reason, to really understand who these people were, how they thought, how they functioned.\n", + "SPEAKER_05 (32'47\"-32'54\"): And her whole life was always trying to understand why they thought the way they did.\n", + "SPEAKER_03 (32'54\"-33'5\"): So you have HUD who thinks they're solving a problem by providing free or subsidized housing, but they kind of have it all wrong, sort of based around individualism and suburbanism.\n", + "SPEAKER_03 (33'5\"-33'8\"): And then you have that in conflict with the Pueblo worldview.\n", + "SPEAKER_07 (33'8\"-33'9\"): Right.\n", + "SPEAKER_07 (33'9\"-33'16\"): And Rina Swentzel really saw Pueblo architecture as an embodiment of the Pueblo worldview.\n", + "SPEAKER_07 (33'16\"-33'24\"): She explained that you could understand a lot about Pueblo life by looking at its buildings and its village layout.\n", + "SPEAKER_05 (33'24\"-33'37\"): The way the village was structured portrayed that kind of community thinking in that there would be the main central ceremonial house, the kiva in the middle.\n", + "SPEAKER_05 (33'37\"-33'46\"): with the outdoor spaces that everybody used, and then these individual spaces for storage and sleeping that surrounded that.\n", + "SPEAKER_07 (33'46\"-33'56\"): And then beyond that central space, Roxanne says, there were buildings for more storage, and then there were the corrals, and then beyond that, there were the fields.\n", + "SPEAKER_05 (33'56\"-34'4\"): There was always this feeling like you could go deeper into the circle or further out, but you always knew which\n", + "SPEAKER_05 (34'4\"-34'7\"): was your circle, and that was your village.\n", + "SPEAKER_05 (34'7\"-34'10\"): So you could always find home.\n", + "SPEAKER_05 (34'10\"-34'12\"): Home wasn't your individual house.\n", + "SPEAKER_05 (34'12\"-34'16\"): It was the center of the village.\n", + "SPEAKER_03 (34'16\"-34'21\"): So I think I know the answer to this, but were the hud homes connected to this traditional structure at all?\n", + "SPEAKER_07 (34'21\"-34'23\"): No, no, they basically weren't.\n", + "SPEAKER_07 (34'23\"-34'32\"): They were built on the outskirts of the Pueblo, and they didn't have a connection to that central ceremonial place that Roxanne described.\n", + "SPEAKER_03 (34'32\"-34'41\"): I mean, I can also imagine that the shift away from building your own home instead of someone making it for you really does change that perspective as well.\n", + "SPEAKER_07 (34'41\"-34'43\"): Yeah, yeah, totally.\n", + "SPEAKER_07 (34'43\"-34'52\"): And making homes was one of the ways that the Pueblo expressed its connection to this place where they had lived for for hundreds and hundreds of years.\n", + "SPEAKER_05 (34'52\"-35'1\"): So you know, you know, you may watch a tree grow up from a little baby tree to a big tree and then cut it down and use it in your house for a vika.\n", + "SPEAKER_05 (35'1\"-35'6\"): But you know that tree, it's your family.\n", + "SPEAKER_05 (35'6\"-35'7\"): The dirt you go\n", + "SPEAKER_05 (35'7\"-35'12\"): get to plaster or make your adobes with and stuff, it's just right there.\n", + "SPEAKER_05 (35'12\"-35'16\"): So you know where the good dirt is and where the not so good dirt is.\n", + "SPEAKER_05 (35'16\"-35'20\"): It's absolutely having a relationship.\n", + "SPEAKER_05 (35'20\"-35'33\"): And when a people stay in a place for many generations with that consciousness intact, the depth of the relationship becomes profound.\n", + "SPEAKER_05 (35'34\"-35'35\"): And so is the houses then.\n", + "SPEAKER_05 (35'35\"-35'39\"): Of course, they would be.\n", + "SPEAKER_03 (35'39\"-35'45\"): Okay, so Roxanne's mom, Rina, she went to architecture school and began writing and developing all these ideas.\n", + "SPEAKER_03 (35'45\"-35'47\"): She wrote about these ideas.\n", + "SPEAKER_03 (35'47\"-35'48\"): You said that she opposed the HUD development.\n", + "SPEAKER_03 (35'48\"-35'52\"): Did she end up really trying to fight the HUD development in Santa Clara?\n", + "SPEAKER_07 (35'52\"-35'53\"): Yeah, she did.\n", + "SPEAKER_07 (35'53\"-35'57\"): And, you know, Roxanne said that that part was really hard for her.\n", + "SPEAKER_07 (35'57\"-36'4\"): You know, she apparently talked with everyone she could talk with about it, but it was kind of an uphill battle.\n", + "SPEAKER_07 (36'4\"-36'15\"): And Roxanne says, you know, there was a disagreement within the Pueblo itself about whether the HUD housing was a good thing or a bad thing.\n", + "SPEAKER_07 (36'15\"-36'15\"): Lots of fights.\n", + "SPEAKER_05 (36'15\"-36'26\"): Lots of disagreements and stuff because there's a lot of people in the community that want to become mainstream and that's where they're going to go and that's okay.\n", + "SPEAKER_05 (36'26\"-36'30\"): Everyone has to decide.\n", + "SPEAKER_05 (36'30\"-36'42\"): But with my mother's help and others like her, there's this sense of like, let's really look at ourselves and see what is going on here so that we can choose.\n", + "SPEAKER_05 (36'42\"-37'2\"): Because if we understand who we've been for thousands of years, and then within a very short time, we're swept into pieces, wow, you know, this is enough to stop and really look at and think about and start to really decide where are we going to go from here.\n", + "SPEAKER_03 (37'2\"-37'3\"): That makes a ton of sense.\n", + "SPEAKER_03 (37'3\"-37'7\"): I mean, you can see totally the perspective of HUD trying to solve this problem.\n", + "SPEAKER_03 (37'7\"-37'14\"): I mean, I grew up in HUD housing, like I would be homeless if it wasn't for HUD, you know, making sure that I had a home when I was a kid.\n", + "SPEAKER_03 (37'14\"-37'22\"): But I wish they would have came into the situation with the same mindset that Rena did, where she's like, I'm going to go to school and understand all of this.\n", + "SPEAKER_03 (37'22\"-37'24\"): They really didn't come in with that mindset, that's for sure.\n", + "SPEAKER_07 (37'26\"-37'27\"): That's true.\n", + "SPEAKER_07 (37'27\"-37'28\"): That is true.\n", + "SPEAKER_07 (37'28\"-37'33\"): And I think in the case of the Pueblos, it's a very particular context.\n", + "SPEAKER_07 (37'33\"-37'47\"): So these are places and people that have experienced multiple waves of conquest and settlement, and they've really had to fight to keep their traditions alive.\n", + "SPEAKER_07 (37'47\"-37'54\"): And so I think for Rina, this felt like one more way that changes were being forced onto the community.\n", + "SPEAKER_05 (37'55\"-38'7\"): I remember my mother being very troubled because it was just one more way the government was assimilating us into the American society.\n", + "SPEAKER_07 (38'7\"-38'14\"): But of course, you know, to your point about the importance of affordable housing, yeah, that situation is complicated.\n", + "SPEAKER_07 (38'14\"-38'23\"): Like in Santa Fe, there can be this obsession with traditional historic styles at the expense of just building out more affordable housing.\n", + "SPEAKER_07 (38'24\"-38'35\"): But then in this Santa Clara example, there was affordable housing coming in that just didn't do enough to acknowledge traditional styles and practices when it comes to housing.\n", + "SPEAKER_03 (38'35\"-38'42\"): Yeah, there's just got to be this balance between building affordable housing and being sensitive to the local context, like everywhere.\n", + "SPEAKER_07 (38'43\"-38'43\"): Right.\n", + "SPEAKER_07 (38'43\"-38'45\"): And you know, it was interesting.\n", + "SPEAKER_07 (38'45\"-39'3\"): There were affordable housing advocates I spoke to while I was researching this story who said, you know, in Santa Fe, if we're interested in building a community that is rooted in historical building practices, the Pueblos do have a lot to teach us.\n", + "SPEAKER_07 (39'3\"-39'10\"): So there are some traditional Pueblo communities, for example, that are four or five stories tall.\n", + "SPEAKER_07 (39'10\"-39'11\"): They're dense.\n", + "SPEAKER_07 (39'11\"-39'14\"): They're multi-unit.\n", + "SPEAKER_07 (39'14\"-39'21\"): And that kind of building is rare in Santa Fe, which is mostly built around the single-family, single-story model.\n", + "SPEAKER_03 (39'21\"-39'21\"): Wow.\n", + "SPEAKER_03 (39'21\"-39'33\"): So, so basically the style of Pueblo architecture that Santa Fe sort of grabbed onto in the historic preservation was just this one really narrow slice of Adobe architecture.\n", + "SPEAKER_03 (39'33\"-39'38\"): But there's so much more to learn from that they could be doing and, and creating dense housing.\n", + "SPEAKER_07 (39'38\"-39'39\"): Yeah.\n", + "SPEAKER_03 (39'39\"-39'41\"): Yeah, definitely.\n", + "SPEAKER_03 (39'41\"-39'47\"): So in the case of Santa Clara, did they eventually choose to include the HUD housing in their community?\n", + "SPEAKER_07 (39'47\"-39'48\"): Yes, they did.\n", + "SPEAKER_03 (39'48\"-39'50\"): And how did it affect the Pueblo?\n", + "SPEAKER_03 (39'50\"-39'51\"): Like what is it like these days?\n", + "SPEAKER_07 (39'51\"-39'59\"): Yeah, I asked Roxanne about that and she said the center of the village still has its old adobe buildings.\n", + "SPEAKER_05 (39'59\"-40'4\"): But the middle of the village has emptied out of a lot of people.\n", + "SPEAKER_05 (40'4\"-40'12\"): It's kind of like a ghost town of sorts and it only gets filled up on feast days or certain occasions.\n", + "SPEAKER_05 (40'13\"-40'19\"): few houses that have people in, but most of the people have moved out to the suburbs.\n", + "SPEAKER_05 (40'19\"-40'23\"): So it broke, it fragmented.\n", + "SPEAKER_07 (40'23\"-40'34\"): But Roxanne says on the positive side, there's been a resurgence of interest in traditional adobe building techniques, and she actually teaches workshops on adobe construction.\n", + "SPEAKER_07 (40'35\"-40'42\"): And she really credits her mom with giving her that sense of possibility when it comes to building.\n", + "SPEAKER_07 (40'42\"-40'51\"): When we were talking, she told me this great story about how her first major building project was this family home that she built with her mom and dad.\n", + "SPEAKER_07 (40'51\"-40'53\"): And she was a young teenager.\n", + "SPEAKER_07 (40'53\"-40'55\"): She was in junior high.\n", + "SPEAKER_05 (40'55\"-40'58\"): I got to build my own bedroom.\n", + "SPEAKER_05 (40'58\"-41'1\"): And I'm a little kid and I got to make my own bedroom.\n", + "SPEAKER_05 (41'1\"-41'4\"): So I built me a stairway up to a bed.\n", + "SPEAKER_05 (41'5\"-41'15\"): that had a neat pattern that went up around it and the stairs were goofy, but they worked, but I could make my own room.\n", + "SPEAKER_05 (41'15\"-41'20\"): I'm so grateful that they gave me the knowing that you can.\n", + "SPEAKER_07 (41'20\"-41'26\"): And so, you know, it's kind of that sense of possibility that she got from her mom.\n", + "SPEAKER_07 (41'26\"-41'34\"): You know, that's what she wants to give other people in the Pueblo, that there's this very long tradition of building there and that, you know, they can do this.\n", + "SPEAKER_03 (41'35\"-41'36\"): Wow, that is so cool.\n", + "SPEAKER_03 (41'36\"-41'37\"): Well, thanks so much, Delaney.\n", + "SPEAKER_03 (41'37\"-41'40\"): I really appreciate you bringing this little extra part of the story to us.\n", + "SPEAKER_07 (41'40\"-41'41\"): Yeah, yeah.\n", + "SPEAKER_07 (41'41\"-41'41\"): Thank you.\n", + "SPEAKER_03 (41'47\"-41'51\"): 99% Invisible was produced this week by our senior producer Delaney Hall.\n", + "SPEAKER_03 (41'51\"-41'54\"): Edited by Emmett Fitzgerald and Katie Mingle.\n", + "SPEAKER_03 (41'54\"-41'55\"): Mixed by Bryson Barnes.\n", + "SPEAKER_03 (41'55\"-41'57\"): Fact-checking by Francis Carr Jr.\n", + "SPEAKER_03 (41'57\"-41'59\"): Music by Sean Real.\n", + "SPEAKER_03 (41'59\"-42'1\"): Kurt Kolstad is the digital director.\n", + "SPEAKER_03 (42'1\"-42'9\"): The rest of the team is Joe Rosenberg, Vivian Leigh, Christopher Johnson, Abby Madon, Chris Berube, Sophia Klatsker, and me, Roman Mars.\n", + "SPEAKER_03 (42'12\"-42'24\"): Special thanks this week to Daniel Werwath, Rose Simpson, and the Archives of American Art at the Smithsonian Institution for the John Gall Meme Oral History Interview, which was conducted on December 3, 1964.\n", + "SPEAKER_03 (42'24\"-42'31\"): Thanks also to Audra Belmore, the curator of the John Gall Meme Archives of Southwestern Architecture at UNM.\n", + "SPEAKER_03 (42'31\"-42'36\"): Finally, special thanks to the Historic Division's partners in the study they conducted.\n", + "SPEAKER_03 (42'36\"-42'45\"): They include New Mexico Health Equity Partnership, Historian and Preservation Planner John Murphy, Six Blooms, and Little Globe Inc.\n", + "SPEAKER_03 (42'45\"-42'51\"): Little Globe has been conducting interviews with people in Santa Fe's Historic District and helped connect us with Ray Herrera.\n", + "SPEAKER_03 (42'52\"-43'6\"): We are a project of 91.7 KALW in San Francisco and produced on Radio Row, which exists in various corners of North America, but in its heart will always be in beautiful downtown Oakland, California.\n", + "SPEAKER_03 (43'7\"-43'12\"): We are a member of Radiotopia from PRX, a collective of the best, most innovative shows in all of podcasting.\n", + "SPEAKER_03 (43'12\"-43'16\"): Discover, listen, and support them all at radiotopia.fm.\n", + "SPEAKER_03 (43'16\"-43'19\"): You can find the show and join discussions about the show on Facebook.\n", + "SPEAKER_03 (43'19\"-43'22\"): You can tweet me at Roman Mars and the show at 99pi.org.\n", + "SPEAKER_03 (43'22\"-43'25\"): We're on Instagram and Reddit too.\n", + "SPEAKER_03 (43'25\"-43'26\"): You like pictures of buildings made of mud?\n", + "SPEAKER_03 (43'26\"-43'27\"): Well, I certainly do.\n", + "SPEAKER_03 (43'27\"-43'29\"): And we got a bunch of them at 99pi.org.\n", + "SPEAKER_11 (43'40\"-43'44\"): Radiotopia from PRX.\n" + ] + } + ], + "source": [ + "def format_seconds(seconds):\n", + " minutes = int(seconds // 60)\n", + " seconds_remainder = int(seconds % 60)\n", + " formatted_time = f\"{minutes}'{seconds_remainder}\\\"\"\n", + " return formatted_time\n", + "\n", + "for r in result:\n", + " start = format_seconds(r['start'])\n", + " end = format_seconds(r['end'])\n", + " print(f\"{r['speaker']} ({start}-{end}): {r['text'].strip()}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9b598a6c-dd2b-4d40-a2ef-b2a514d98680", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of classified speakers: 12\n" + ] + } + ], + "source": [ + "speakers = set([r[\"speaker\"] for r in result])\n", + "print(f\"Number of classified speakers: {len(speakers)}\")" + ] + }, + { + "cell_type": "markdown", + "id": "4c6ba36f-a07a-4e24-9a36-bb40afc7b127", + "metadata": {}, + "source": [ + "Of course, the model doesn't take care of the physical names of the speakers - we can possibly put this into an LLM to ground the speakers to the names mentioned in the text, but that's story for another day. During this demo, we have manually looked and identified the following speaker names:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "c0646565", + "metadata": {}, + "outputs": [], + "source": [ + "speaker_names = {\n", + " \"SPEAKER_00\": \"FROM NEWS CLIP\",\n", + " \"SPEAKER_01\": \"FROM NEWS CLIP\",\n", + " \"SPEAKER_02\": \"Trey Jordan\",\n", + " \"SPEAKER_03\": \"Roman Mars\",\n", + " \"SPEAKER_04\": \"FROM NEWS CLIP\",\n", + " \"SPEAKER_05\": \"Roxanne Swentzell\",\n", + " \"SPEAKER_06\": \"Joseph Montoya\",\n", + " \"SPEAKER_07\": \"Delaney Hall\",\n", + " \"SPEAKER_08\": \"Lisa Gavioli Roach\",\n", + " \"SPEAKER_09\": \"Ray Herrera\",\n", + " \"SPEAKER_10\": \"Chris Wilson\",\n", + " \"SPEAKER_11\": \"FROM NEWS CLIP\",\n", + "}\n", + "real_speakers = set(speaker_names.values())" + ] + }, + { + "cell_type": "markdown", + "id": "8c71d99d-12f2-4812-8573-3cbbd23a68a0", + "metadata": {}, + "source": [ + "When a speaker speaks for a long time, the model might chunk it to different segments. To show the whole conversation in a more meaningful way, let's combine segments of the same speaker, and display the conversation." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "58a7ce67", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Roman Mars (0'0\"-0'20\"): This is 99% Invisible. I'm Roman Mars. Back in the early 2000s, an architect named Trey Jordan wrote a letter to Santa Fe, New Mexico's Historic Preservation Division, laying out the details of a house he was hoping to build in the city's historic district. The process started out pretty normal.\n", + "\n", + "Trey Jordan (0'20\"-0'28\"): We were just not ready for what happened. I mean, I don't remember the process being that thorny.\n", + "\n", + "Roman Mars (0'28\"-0'35\"): The first indication that things maybe wouldn't go smoothly had to do with the color of the stucco that Trey wanted to use.\n", + "\n", + "Trey Jordan (0'35\"-0'51\"): I do recall that in my proposal letter, I had mentioned that the stucco color would be a custom color similar to, I think it was cottonwood, which is its standard color of a commercially available stucco.\n", + "\n", + "Delaney Hall (0'51\"-0'59\"): Buildings in the Historic District have to follow a number of design guidelines so that they fit in with Santa Fe's traditional Adobe look.\n", + "\n", + "Roman Mars (0'59\"-1'0\"): Senior producer Delaney Hall.\n", + "\n", + "Delaney Hall (1'1\"-1'37\"): The style, called Pueblo Revival, comes from indigenous Pueblo architecture and the area's old Spanish missions. Think low-brown buildings with smooth edges. In the historic district, buildings can only be so tall, windows have to be a certain distance from the corners, roofs generally have to be flat, and stuccoes have to be earth tone. And the stucco Trey wanted to use, the color that was close to cottonwood, it was an earth tone. It was just a little different than usual. Still, the board approved it. But then things started to get weird.\n", + "\n", + "Trey Jordan (1'37\"-2'0\"): When we stuccoed the house, it got back to me that two of the board members were very upset about the color, and they took samples of cottonwood over to the house to hold it up to the stucco. Well, of course, it didn't match cottonwood, but as I said in my letter, it would be a custom color similar to, and I think it was quite obvious that it was.\n", + "\n", + "Delaney Hall (2'0\"-2'7\"): There were other subtle ways that the house was different from the traditional Santa Fe look. The corners, for instance.\n", + "\n", + "Trey Jordan (2'7\"-2'17\"): So the corners were sharp, not round, not the ooey-gooey Pueblo Revival look, but a little more crisp than that, geometric.\n", + "\n", + "Delaney Hall (2'17\"-2'44\"): I've seen this house and it's a bit modern, a bit angular. But honestly, it is not wildly different from the surrounding homes, which are done in a more traditional style. And even with the bumps in the process, like the disagreement about the stucco, Trey just wasn't expecting what happened next. A few weeks after his clients had moved in, Trey got a call from them. The house had been defaced in the middle of the night.\n", + "\n", + "Trey Jordan (2'44\"-2'58\"): You know, it was really, really frightening and really, really shocking that someone would get so angry that they would terrorize another family by defacing their house with a swastika and writing the words Nazi architecture on it.\n", + "\n", + "Delaney Hall (2'58\"-3'4\"): Nazi architecture had been painted on the side of the house. They don't know who did it.\n", + "\n", + "Trey Jordan (3'4\"-3'10\"): I was so just completely shocked and frankly scared. You know, I was really, I just thought, what is going on?\n", + "\n", + "Delaney Hall (3'12\"-3'15\"): Why do you think they wrote Nazi architecture?\n", + "\n", + "Trey Jordan (3'15\"-3'27\"): You know, I don't know if they just felt it was too strong or too modern. We think it was a comment about wanting to stop buildings like this from happening in the historic districts.\n", + "\n", + "Delaney Hall (3'27\"-3'37\"): If you're not from Santa Fe, this whole incident probably strikes you as totally absurd. And to be fair, even people from Santa Fe marveled at this when it went down.\n", + "\n", + "Trey Jordan (3'38\"-3'56\"): You know, there was some period of time thereafter where people would want to drive by and see it because, of course, it became, in this unfortunate way, it became notable. And it was so funny because so many people would call me and they'd just say, I don't understand what the problem is here. I just don't see it. I don't get it.\n", + "\n", + "Delaney Hall (3'57\"-4'10\"): I love the Pueblo Revival style. It's part of what gives Santa Fe its very distinctive look. It looks like no other city in the U.S., like no other city in the world. And people here are proud of that.\n", + "\n", + "Roman Mars (4'11\"-4'30\"): But for some in the city, historic preservation is a very serious business. The aesthetics of Santa Fe have been carefully crafted and preserved, and deviating from those aesthetics is seen, at least by some, as a serious offense. You know, and I'm gonna call you a Nazi level of offense.\n", + "\n", + "Delaney Hall (4'31\"-4'45\"): And this battle over style goes back more than a hundred years, ever since a group of early preservationists set out a vision for Santa Fe's architecture and, in the process, dramatically transformed the town.\n", + "\n", + "Roman Mars (4'47\"-5'1\"): Adobe has a long history in northern New Mexico. Building with mud goes back hundreds and hundreds of years. The technique was favored both by the indigenous people of the region and by the Spanish settlers who arrived later on.\n", + "\n", + "Delaney Hall (5'1\"-5'15\"): But back in the 1800s, when New Mexico was vying to become a state, Santa Fe actually tried to leave its mud-based architecture behind. The city constructed buildings that screamed, hey, we're just like you guys.\n", + "\n", + "Chris Wilson (5'15\"-5'18\"): They were Italianate business blocks on the plaza.\n", + "\n", + "Delaney Hall (5'18\"-5'20\"): Architectural historian Chris Wilson.\n", + "\n", + "Chris Wilson (5'21\"-5'32\"): schools and kind of a red brick Romanesque style, a 1900 neoclassical capital that would have been at home in any of the other new states.\n", + "\n", + "Roman Mars (5'32\"-5'50\"): Local leaders hoped this architectural posturing would help convince Congress to let New Mexico into the Union. They were well aware that East Coasters viewed them with some suspicion. The territory seemed like a dusty foreign outpost, unlikely to integrate into mainstream American culture.\n", + "\n", + "Delaney Hall (5'51\"-6'6\"): Eventually, in 1912, after more than 60 years of trying, New Mexico became a state. But all of these attempts to fit in, they ended up being a bad thing. Especially for New Mexico's newly minted capital, Santa Fe.\n", + "\n", + "Roman Mars (6'6\"-6'22\"): Santa Fe was struggling economically. There was a railroad that went through New Mexico, but despite being called the Santa Fe Railroad, it didn't go directly through Santa Fe, and the city couldn't develop any serious industries without good rail access.\n", + "\n", + "Delaney Hall (6'22\"-6'42\"): Santa Fe was rapidly shrinking, and so the mayor at the time put together a planning board and told them to come up with a plan to save the city. they landed on tourism. Tourists had already started to come to Santa Fe in small numbers, but the board noticed that when they arrived, they weren't that impressed.\n", + "\n", + "Chris Wilson (6'42\"-6'57\"): Once they see our Americanized city, they press on, they press north to the Pueblos. Tourism can be our salvation, but only if we reverse the ill-conceived Americanization of the last three decades.\n", + "\n", + "Delaney Hall (6'57\"-7'20\"): The board wrote up a document that's become known as the 1912 plan. They recommended the city preserve its traditional Adobe architecture, but the plan went even further. It said that any new development should also be done in the Santa Fe style. They wanted to create a kind of citywide architectural brand based on the historical precedent.\n", + "\n", + "Roman Mars (7'20\"-7'31\"): The sweeping scope of the 1912 plan was pretty radical. At the time, most historic preservation in the U.S. focused on the homes of important old white guys.\n", + "\n", + "Chris Wilson (7'31\"-7'36\"): Mount Vernon, Monticello. So preservation was focused on single buildings.\n", + "\n", + "Roman Mars (7'36\"-7'49\"): Santa Fe, on the other hand, decided to focus on the everyday architecture of its ordinary people, and it expanded preservation beyond single buildings to the entire community. A city had never tried something so far-reaching.\n", + "\n", + "Delaney Hall (7'49\"-8'4\"): But many of the leaders behind the effort believed that this could be Santa Fe's salvation. Not in pretending to be a conventional American city, but in embracing its difference and selling it to outsiders.\n", + "\n", + "FROM NEWS CLIP (8'4\"-8'12\"): To those who are devotees of the great outdoors, to the splendors of its vastness and magnificent scenery, the urge is west to the Indian country.\n", + "\n", + "Delaney Hall (8'13\"-8'34\"): Santa Fe's tourism campaign took off. By the 19-teens, a wave of mostly white newcomers began arriving in the state. They were artists and anthropologists and health seekers. Chris Wilson calls them internal expats, the kind of people who might have gone to Paris, but instead went to Santa Fe.\n", + "\n", + "Roman Mars (8'34\"-8'36\"): And one of those newcomers was John Gaw Meem.\n", + "\n", + "FROM NEWS CLIP (8'36\"-8'42\"): I became particularly aware of New Mexican architecture while lying in bed.\n", + "\n", + "Delaney Hall (8'43\"-8'55\"): John Gaw Meem was a civil engineer who'd come to Santa Fe from New York to recover from tuberculosis. And while he was recuperating, he became enthralled with the architecture.\n", + "\n", + "FROM NEWS CLIP (8'55\"-9'6\"): And I decided then and there, even though I was, I thought, getting very advanced in years, I'd better change my profession. And what I really wanted to be was an architect.\n", + "\n", + "Roman Mars (9'7\"-9'19\"): And so at the very advanced age of 27, Meem switched careers and quickly became Santa Fe's go-to architect, especially for wealthy transplants from the East Coast and Midwest.\n", + "\n", + "Chris Wilson (9'19\"-9'25\"): But also then of important public buildings, churches, county courthouse, and so forth.\n", + "\n", + "Delaney Hall (9'25\"-9'44\"): Meem became the leading architect of the Santa Fe style, and he helped to bring a very old building tradition into the modern era. he didn't always use actual mud bricks. He used reinforced concrete and steel to create an adobe-ish take on that old style.\n", + "\n", + "Roman Mars (9'44\"-9'51\"): And his work helped the city of Santa Fe actually create the architectural brand it had imagined.\n", + "\n", + "FROM NEWS CLIP (9'51\"-10'9\"): And I think it's perfectly legitimate, not only legitimate, but almost a duty in a part of the world where we have native architecture with these wonderful shapes that we should recall them. It's worth preserving. I certainly agree with you 100% on that, as you know.\n", + "\n", + "Delaney Hall (10'9\"-10'22\"): All over town, new buildings went up in this adobe style. And as far as attracting tourists, it worked. Between 1920 and 1930, Santa Fe went from 200 hotel rooms to 600.\n", + "\n", + "Roman Mars (10'22\"-10'29\"): Everything was going great until a pesky new form of architecture showed up on the scene, threatening to ruin everything.\n", + "\n", + "Delaney Hall (10'30\"-10'45\"): In the 1950s, architectural modernism was spreading, even in Santa Fe. The city was growing, the tourist industry was driving more development, and there was a sense that Santa Fe was losing its grip on the style that had made it so distinct.\n", + "\n", + "Chris Wilson (10'45\"-10'55\"): And the traditionalist community that had reached this consensus around the revival style becomes alarmed, and they react against it.\n", + "\n", + "Roman Mars (10'55\"-11'20\"): And so the preservationists, with John Gaumeme as one of their leaders, doubled down. In 1957, the city passed an ordinance that required the Santa Fe style. It elaborated a number of sub-styles and created a large historic district in the center of the city, which included some of Santa Fe's oldest neighborhoods. They were full of Hispanic families. Some of them had lived for generations in adobe homes built by their ancestors.\n", + "\n", + "Delaney Hall (11'21\"-11'40\"): With this new ordinance, any changes to a building in the district now had to be approved by a design board. And at first, critics worried mostly about aesthetics. They thought the look of the city would become boring and homogenous, or that it would turn into a kind of hokey Old West stage set.\n", + "\n", + "Chris Wilson (11'40\"-11'51\"): They weren't against the city having a distinctive character, but they just doubted that the style guidelines were going to do it in the most vibrant living way.\n", + "\n", + "Delaney Hall (11'51\"-11'57\"): And were there questions raised about what the ordinance might do to affordability in the central city?\n", + "\n", + "Chris Wilson (11'57\"-12'4\"): No, there weren't arguments about, you know, potential gentrification, as we would call it now.\n", + "\n", + "FROM NEWS CLIP (12'4\"-12'15\"): Finally tonight, the sound of moving that roar you hear in the American Southwest these days is the traffic heading to Santa Fe, New Mexico. The population is up 12 percent over the past decade.\n", + "\n", + "Delaney Hall (12'15\"-12'29\"): Over the next couple decades, Santa Fe got hit with a huge wave of tourism and resettlement. In the 1970s, there was an oil boom in neighboring Texas, and a bunch of newly rich Texans moved to Santa Fe.\n", + "\n", + "Roman Mars (12'29\"-12'45\"): Then in the 1980s, as international travel became more of a thing, Santa Fe became not just a national destination, but an international one. The city had spent decades perfecting its tourist identity, figuring out how to package and sell itself. Maybe too effectively.\n", + "\n", + "Chris Wilson (12'45\"-12'56\"): The readers of Condé Nast's travel magazine in the early 1980s bought Santa Fe their number one tourist destination, not just in the United States, but in the world.\n", + "\n", + "Roman Mars (12'57\"-13'7\"): A million, sometimes two million tourists started coming every year. This was in a town of 50 or 60,000 residents. Santa Fe started to get totally overrun by these visitors.\n", + "\n", + "Delaney Hall (13'7\"-13'16\"): And some of these visitors decided to buy up more of the city's old historic homes. This was gentrification, but, like, on steroids.\n", + "\n", + "Chris Wilson (13'16\"-13'34\"): These are the 1% or the one-tenth of 1%, the very wealthiest of people, who start to have multiple homes. They have a pied-à-terre in Manhattan, and they've got a house in Nantucket, and maybe a pied-à-terre in Paris, and now they want to have a house in Santa Fe.\n", + "\n", + "FROM NEWS CLIP (13'35\"-13'50\"): In Santa Fe, the neighborhoods are changing as fast as the builders can put up new buildings. There aren't a lot of barrios left. They're all becoming playgrounds for the rich. For the first time since 1600, there are now more Anglos here than there are Hispanics.\n", + "\n", + "Delaney Hall (13'50\"-14'0\"): It was during the 90s that Trey Jordan, the architect, started working for an architecture firm in Santa Fe. And he loved learning to build in the Santa Fe style.\n", + "\n", + "Trey Jordan (14'1\"-14'8\"): It's a vernacular that I think a lot of people find it easy to like. I mean, there's something quite charming about it.\n", + "\n", + "Delaney Hall (14'8\"-14'17\"): But he could also understand the irony of what was happening. How this old tradition had become in vogue with Santa Fe's wealthy newcomers.\n", + "\n", + "Trey Jordan (14'17\"-14'33\"): It's more or less a vernacular of poverty and a vernacular of survival. And we spend extraordinary amounts of money to nowadays reproduce a style that was really, you know, born out of necessity.\n", + "\n", + "Delaney Hall (14'34\"-15'12\"): Over time, the city implemented more restrictions and more code. The historic districts expanded. Limits were placed on the height of buildings. Commercial districts were encouraged to adopt the Adobe look. And so Santa Fe began to have stuff like a fake Adobe iHop and a fake Adobe Panda Express. A wave of brown stucco washed over the city. The 80s and 90s were a tough time for a lot of people in Santa Fe. I asked one old-timer, Joseph Montoya, what it was like living here during those years, and he thought for a couple moments before saying, it sucked.\n", + "\n", + "Joseph Montoya (15'12\"-15'24\"): I think what happened, whether it was appropriate or not, a building resentment over like, gosh, we've got a lot of fine restaurants now in town that we didn't have before, right? I can't eat in them.\n", + "\n", + "Delaney Hall (15'24\"-15'28\"): Joseph's family connection to Santa Fe goes back generations.\n", + "\n", + "Joseph Montoya (15'29\"-15'34\"): I don't go to the plaza because it's no longer my plaza. I don't feel comfortable in my own town.\n", + "\n", + "Delaney Hall (15'34\"-15'53\"): Joseph joined the city government in 1990. He's now the executive director of the County Housing Authority. Back then, he was also working on community development and housing issues. And the first thing he did was review some studies the city had already done, trying to understand why locals couldn't afford to live here anymore.\n", + "\n", + "Roman Mars (15'54\"-16'4\"): He says that there was even one study that tried to actually quantify the cost of the Santa Fe style, like the exposed wood beams that support the ceilings in many homes.\n", + "\n", + "Joseph Montoya (16'4\"-16'17\"): How much do vehicles cost? Is there a cost difference between the kind of windows you have to put in or not, or different doors? And they tried to add up that cost over and above what you might have to pay anyway.\n", + "\n", + "Roman Mars (16'17\"-16'38\"): And yeah, the carved wood beams and the ornamental corbeling, for example, did add some costs, but that wasn't really the central issue. More relevant was the number of wealthy buyers flooding the city and driving up the cost of everything, including land. The city just couldn't build enough subsidized housing to keep lower-income people housed.\n", + "\n", + "Delaney Hall (16'38\"-16'56\"): And that was partly because some of those newcomers began to fight new construction. Not just in the historic district, but across the city. Joseph talks about the arguments they would make at community meetings. They would speak out against more density, more infill housing, taller buildings.\n", + "\n", + "Joseph Montoya (16'56\"-17'18\"): They would say, This is going to ruin the quality of my life. I bought here expecting it to always stay the same because the community character is important to me. And it was seen as you were being a good citizen, right? And, you know, I think that's something that worked for a lot of people, right? That, oh yeah, development is what ruined this city, and now we're going to stop it.\n", + "\n", + "Delaney Hall (17'18\"-17'26\"): But all the talk about community character always frustrated Joseph. Because what community were they talking about? And what character?\n", + "\n", + "Joseph Montoya (17'26\"-17'46\"): So it's like, My God, you know, I know exactly that place they're talking about. We used to hunt rabbits there. And so that was the community character back then. And previous to that, that was a Native American campground. So what character are we taking? You know, the character that was created in 1973.\n", + "\n", + "Delaney Hall (17'46\"-17'51\"): Joseph watched in dismay as the Nimbys gained political power and influence.\n", + "\n", + "Joseph Montoya (17'52\"-18'15\"): I felt that if we've gotten to the point where there's a majority of people that the politicians were listening to that can make these arguments and win, the city has been lost. It was sad to see the demise, the complete demise of families and history and legacy being washed away.\n", + "\n", + "Roman Mars (18'20\"-18'47\"): In some ways, Santa Fe had become a victim of its own success. The early preservationists set out a vision for protecting Santa Fe's historic look, and they helped create a tourism industry that's still the foundation of the city's economy. But the popularity of Santa Fe has also helped to create serious inequality. The town became an increasingly expensive place to live, and lots of people work in hospitality, taking care of tourists and making service economy wages.\n", + "\n", + "Delaney Hall (18'47\"-20'7\"): Locals who were pushed out of the historic district moved to the more affordable south side. Now many of them can't even afford to live there. Of the 80 cousins Joseph grew up with, he says only five are still in the city. These days, more than half of the people who work in Santa Fe don't live here, including Joseph. He lives in Albuquerque, commuting from an hour away to fight for affordable housing in his old hometown. Up until recently, I lived on the historic east side of Santa Fe, in a blocky and frankly unattractive yellow stucco house surrounded by gorgeous multi-million dollar adobe homes. And it was a strange place to live. I would sometimes find myself walking through the neighborhood as evening approached and the sky got dark, and I was always struck by the number of homes in which the lights just never came on. The neighborhood was eerily quiet. Down the street from me, there was an old adobe house that no one seemed to live in. There was never a car in the driveway. I literally never saw someone come or go. But landscapers would come in a couple times a month to mow the lawn and trim the trees. It was a beautifully maintained, seemingly empty specimen.\n", + "\n", + "Lisa Gavioli Roach (20'8\"-20'20\"): We've been very intent on preserving the architectural character of our historic districts, but what has fallen through the cracks has been the community character and how that has really changed.\n", + "\n", + "Delaney Hall (20'20\"-20'49\"): This is Lisa Gavioli-Roach. She first worked in the Historic Preservation Division as a senior planner, and she said it often felt like they managed the districts as if the buildings were works of art in a museum. There was little discussion, she said, of the people who actually lived in those neighborhoods. She started to question everything about her field. And then she became the head of the division, which put her in a position to try and make some changes.\n", + "\n", + "Roman Mars (20'49\"-20'57\"): Now Lisa says it's a mistake for preservationists to focus exclusively on the built environment of a neighborhood. Neighborhoods aren't just a collection of buildings.\n", + "\n", + "Lisa Gavioli Roach (20'58\"-21'8\"): It's not just visual character that you're looking at. It's the sounds that you hear, the smells that you smell, the people that you interact with. All of those things contribute to a community's character.\n", + "\n", + "Delaney Hall (21'9\"-21'21\"): And those things have been dramatically altered in the historic neighborhoods of Santa Fe over the past few decades. You don't often hear kids playing or see neighbors talking to each other over a fence.\n", + "\n", + "Lisa Gavioli Roach (21'21\"-21'31\"): You're seeing tourists taking photos and you yourself start to feel like you're just like a character in a diorama or something. You know, it starts to feel very different.\n", + "\n", + "Roman Mars (21'31\"-21'40\"): The transformation of Santa Fe's old neighborhoods is complex. It's not like historic preservation is entirely at fault, but Lisa does think it's played a role.\n", + "\n", + "Lisa Gavioli Roach (21'41\"-22'2\"): The city's approach to preservation is highly prescriptive, down to every single detail. Any exterior change has to come through our office, and most of them need a permit, even if you're fixing your fence or repainting your windows or, you know, little minor things like that. It feels very invasive, I think, for many people.\n", + "\n", + "Delaney Hall (22'3\"-22'13\"): And the process is also expensive. It often requires hiring an architect. It's just one more thing that can make it hard for old-timers to stay in their homes.\n", + "\n", + "Lisa Gavioli Roach (22'13\"-22'41\"): You know, I was speaking to a homeowner just last week who was talking to me about her experience renovating her grandfather's home. And she just said the whole time that she was going through it, she really felt like it was tearing her family apart. And she just wondered, what are we preserving? She just kept saying that, what are we preserving? because certainly my family's not being preserved, my family's connection to this place is not being respected, and it's so arduous just to get through it.\n", + "\n", + "Roman Mars (22'41\"-22'58\"): Over the past eight months or so, the Historic Division has been working on a study to quantify the changes that have happened in the city's historic districts over the years. They've found that between 1980 and 2018, even as the population of Santa Fe grew, the historic districts emptied out.\n", + "\n", + "Delaney Hall (22'59\"-23'11\"): Old families left, and their homes turned into second homes or short-term rentals. The people who now live in the historic district are generally white, wealthy, and old.\n", + "\n", + "Lisa Gavioli Roach (23'11\"-23'47\"): The gentrification of our historic neighborhoods is all but complete. And in many ways, it's not reversible. And I think instead of just singularly celebrating historic preservation for creating and maintaining this tourist economy, We have to recognize that there have been other experiences here as well and that the outcomes for our community are not all good. Is this really what we want? What do we value now in our community? It's not 1957 anymore. It's not 1912 anymore.\n", + "\n", + "Delaney Hall (23'47\"-24'9\"): There was one person I met while working on this story who embodied the complicated and sometimes contradictory relationship that Santa Fe has to its own past. Like Joseph, Ray Herrera's family has lived in Santa Fe for many generations. Ray grew up building and maintaining his family's old adobe homes.\n", + "\n", + "Ray Herrera (24'9\"-24'21\"): Everybody built with adobe back then. I guess you could say it's in your blood. If you're a local Hispanic like me, whose parents and grandparents and great-grandparents were from Santa Fe, you know, originally,\n", + "\n", + "Delaney Hall (24'22\"-24'40\"): Ray still lives in the Historic District. His family is one of the few remaining so-called legacy families, and he's watched as many of his neighbors and friends have been forced to leave. But he still supports the work of Historic Preservation. In fact, he's extremely committed to it.\n", + "\n", + "Ray Herrera (24'41\"-24'44\"): I was there at every meeting for 20-some years.\n", + "\n", + "Delaney Hall (24'44\"-24'58\"): Every week, Ray would show up at the H-Board meetings to testify. He would remind new homeowners about the history of the neighborhood, about who used to live in their houses, and about what Santa Fe used to be like.\n", + "\n", + "Ray Herrera (24'58\"-25'3\"): The buildings speak for the people that were here a hundred years ago.\n", + "\n", + "Delaney Hall (25'4\"-25'18\"): Ray says his family and friends don't really understand his interest in preservation. For many of them, the historic districts and the whole project of preservation seems to be entirely in the interest of white homeowners.\n", + "\n", + "Ray Herrera (25'18\"-25'53\"): And my relatives and friends that don't live here anymore, they tell me, why do you spend your time fighting for the Anglos? And I said, I'm not fighting for the Anglos. I'm fighting to protect the small town feeling of Santa Fe. That's what I try to preserve. You know, if it were up to these home builders and developers, we'd have homes running up and down the Santa Fe River.\n", + "\n", + "Delaney Hall (25'53\"-26'2\"): And you don't think it's worth it, even if it, say, Let Hispanic people who've been here for generations be here.\n", + "\n", + "Ray Herrera (26'2\"-26'12\"): The thing is that it's sort of too late to say that anymore because 90 percent of the Hispanic families have moved out.\n", + "\n", + "Delaney Hall (26'15\"-26'42\"): It's almost as if, unable to preserve the actual community of his neighborhood, the people he used to know, the neighbors he grew up with, Ray now has to be content to preserve the buildings they left behind. Over the years, Ray has fought every kind of development you can imagine. Development in the historic district, high-end housing developments, affordable housing developments.\n", + "\n", + "Ray Herrera (26'43\"-26'54\"): anything. Rey Herrera was there fighting anything. If I showed up to a meeting, everybody stopped and looked and said, Oh God, what's happening? Rey Herrera is here.\n", + "\n", + "Delaney Hall (26'55\"-27'13\"): After watching Santa Fe change so much over his lifetime, Ray now resists every change he can. He's holding tight to an idea that many in Santa Fe believe deeply. It's a philosophy of urban planning that could be summed up as, if we don't build it, they won't come.\n", + "\n", + "Joseph Montoya (27'13\"-27'18\"): Well, if we don't build it, we're going to stay the same. And we want to stay the same.\n", + "\n", + "Delaney Hall (27'18\"-27'19\"): Joseph Montoya again.\n", + "\n", + "Joseph Montoya (27'19\"-27'41\"): And that is simply Not true, right? What happens is the fittest survive, right? And people eventually get priced out of their ability to stay here. Change is just a part of life, and so you either accept it and try to take advantage of it, or you try to deny it and you get run over by it.\n", + "\n", + "Roman Mars (27'41\"-27'54\"): The early preservationists tried to freeze Santa Fe at a particular moment in time. The style that they defined in 1912 and then codified in 1957, largely remains the style of the city today.\n", + "\n", + "FROM NEWS CLIP (27'54\"-28'5\"): If this had not been done, we would have lost, I think, the kind of city that Santa Fe is right now.\n", + "\n", + "Delaney Hall (28'5\"-28'50\"): When John Dahmeim said that, the city that Santa Fe is right now, it was 1964. He and the other preservationists couldn't have predicted the changes that would sweep over the city in the decades since then. But in holding on so tight to the architecture of that time, we've actually already lost a lot of the people and cultures that used to make Santa Fe what it was. And people like Joseph Montoya believe that if we don't change course, if we don't allow for more development and more housing, the rest of Santa Fe will follow suit. The whole city will become a kind of museum of culture's past, with only the buildings reflecting who once lived here.\n", + "\n", + "Roman Mars (28'55\"-29'18\"): Coming up after the break, we'll learn more about the Pueblo building traditions that form the basis for the Santa Fe style. So we're back with Delaney again, and you have another story related to the Santa Fe style that you wanted to share with us. So, um, so where should we start?\n", + "\n", + "Delaney Hall (29'18\"-29'40\"): Well, I wanted to start with Roxanne Swensell. She's an artist and builder from Santa Clara Pueblo. And for people who aren't familiar with the pueblos here in New Mexico, they're indigenous communities that, you know, in some cases go back for millennia. So they have a very longstanding connection to this place.\n", + "\n", + "Roman Mars (29'40\"-29'40\"): Very long.\n", + "\n", + "Delaney Hall (29'41\"-30'17\"): Yeah, and I would say in general, Santa Fe has a pretty complicated relationship with the surrounding Pueblos. You know, the city has built a tourism industry largely around indigenous art and culture, and so architecture is just one example of that. And so when we talk about the Pueblo Revival style, it's right there in the name. It's an interpretation or an appropriation of Pueblo design. And so I was curious to talk with Roxanne about, you know, what she makes of the architecture in Santa Fe.\n", + "\n", + "Roxanne Swentzell (30'17\"-30'39\"): You know, there's a charming perspective. I can understand somebody coming in from somewhere else and thinking, this is different. This is kind of unique. For us that grew up here, I find it incredibly distasteful. And we joke, we call Santa Fe, Santa fake. because of the fake Adobe.\n", + "\n", + "Delaney Hall (30'39\"-31'25\"): So there were a couple of reasons I wanted to speak with Roxanne. One is that she has a long history of building real Adobe houses. She's built 20 over the course of her life so far. And the other reason is that her mom, Rina Swentzel, wrote a lot about the disconnect between Pueblo ideas about architecture and, you know, European or I guess Western ideas about architecture. And Rina died in 2015, but Roxanne told me about how she got interested in architecture in the first place. And it all went back to this conflict at the Pueblo in the 1970s. And what happened is that the government, HUD basically, came into Santa Clara to build new housing.\n", + "\n", + "Roxanne Swentzell (31'25\"-31'41\"): But the houses had nothing to do with our cultural ways of life or values. But they were cheap and free. So, you know, people weren't going to turn that away. But my mother was desperate to see if she could stop it.\n", + "\n", + "Roman Mars (31'43\"-31'46\"): And so why exactly did Reno want to stop it?\n", + "\n", + "Delaney Hall (31'46\"-31'54\"): The hud houses were basically suburban in their design. You know, they were these single family homes.\n", + "\n", + "Roxanne Swentzell (31'54\"-32'21\"): Where it's individual thinking, you have your own yard, you keep your neighbor out, you have your prefab house that you didn't make yourself. materials that you can't just go down the hill and dig up your mud and make a house. You have to have money to buy the materials. The way the houses were designed had to do with a lifestyle that was foreign to Pueblo lifestyle.\n", + "\n", + "Delaney Hall (32'21\"-32'37\"): And so Rina actually enrolled at the School of Architecture and Planning at UNM in Albuquerque. And Roxanne said that she really felt like she couldn't fight this new HUD development without first understanding the thinking behind it.\n", + "\n", + "Roxanne Swentzell (32'37\"-32'54\"): So she was very highly educated for that reason, to really understand who these people were, how they thought, how they functioned. And her whole life was always trying to understand why they thought the way they did.\n", + "\n", + "Roman Mars (32'54\"-33'8\"): So you have HUD who thinks they're solving a problem by providing free or subsidized housing, but they kind of have it all wrong, sort of based around individualism and suburbanism. And then you have that in conflict with the Pueblo worldview.\n", + "\n", + "Delaney Hall (33'8\"-33'24\"): Right. And Rina Swentzel really saw Pueblo architecture as an embodiment of the Pueblo worldview. She explained that you could understand a lot about Pueblo life by looking at its buildings and its village layout.\n", + "\n", + "Roxanne Swentzell (33'24\"-33'46\"): The way the village was structured portrayed that kind of community thinking in that there would be the main central ceremonial house, the kiva in the middle. with the outdoor spaces that everybody used, and then these individual spaces for storage and sleeping that surrounded that.\n", + "\n", + "Delaney Hall (33'46\"-33'56\"): And then beyond that central space, Roxanne says, there were buildings for more storage, and then there were the corrals, and then beyond that, there were the fields.\n", + "\n", + "Roxanne Swentzell (33'56\"-34'16\"): There was always this feeling like you could go deeper into the circle or further out, but you always knew which was your circle, and that was your village. So you could always find home. Home wasn't your individual house. It was the center of the village.\n", + "\n", + "Roman Mars (34'16\"-34'21\"): So I think I know the answer to this, but were the hud homes connected to this traditional structure at all?\n", + "\n", + "Delaney Hall (34'21\"-34'32\"): No, no, they basically weren't. They were built on the outskirts of the Pueblo, and they didn't have a connection to that central ceremonial place that Roxanne described.\n", + "\n", + "Roman Mars (34'32\"-34'41\"): I mean, I can also imagine that the shift away from building your own home instead of someone making it for you really does change that perspective as well.\n", + "\n", + "Delaney Hall (34'41\"-34'52\"): Yeah, yeah, totally. And making homes was one of the ways that the Pueblo expressed its connection to this place where they had lived for for hundreds and hundreds of years.\n", + "\n", + "Roxanne Swentzell (34'52\"-35'39\"): So you know, you know, you may watch a tree grow up from a little baby tree to a big tree and then cut it down and use it in your house for a vika. But you know that tree, it's your family. The dirt you go get to plaster or make your adobes with and stuff, it's just right there. So you know where the good dirt is and where the not so good dirt is. It's absolutely having a relationship. And when a people stay in a place for many generations with that consciousness intact, the depth of the relationship becomes profound. And so is the houses then. Of course, they would be.\n", + "\n", + "Roman Mars (35'39\"-35'52\"): Okay, so Roxanne's mom, Rina, she went to architecture school and began writing and developing all these ideas. She wrote about these ideas. You said that she opposed the HUD development. Did she end up really trying to fight the HUD development in Santa Clara?\n", + "\n", + "Delaney Hall (35'52\"-36'15\"): Yeah, she did. And, you know, Roxanne said that that part was really hard for her. You know, she apparently talked with everyone she could talk with about it, but it was kind of an uphill battle. And Roxanne says, you know, there was a disagreement within the Pueblo itself about whether the HUD housing was a good thing or a bad thing. Lots of fights.\n", + "\n", + "Roxanne Swentzell (36'15\"-37'2\"): Lots of disagreements and stuff because there's a lot of people in the community that want to become mainstream and that's where they're going to go and that's okay. Everyone has to decide. But with my mother's help and others like her, there's this sense of like, let's really look at ourselves and see what is going on here so that we can choose. Because if we understand who we've been for thousands of years, and then within a very short time, we're swept into pieces, wow, you know, this is enough to stop and really look at and think about and start to really decide where are we going to go from here.\n", + "\n", + "Roman Mars (37'2\"-37'24\"): That makes a ton of sense. I mean, you can see totally the perspective of HUD trying to solve this problem. I mean, I grew up in HUD housing, like I would be homeless if it wasn't for HUD, you know, making sure that I had a home when I was a kid. But I wish they would have came into the situation with the same mindset that Rena did, where she's like, I'm going to go to school and understand all of this. They really didn't come in with that mindset, that's for sure.\n", + "\n", + "Delaney Hall (37'26\"-37'54\"): That's true. That is true. And I think in the case of the Pueblos, it's a very particular context. So these are places and people that have experienced multiple waves of conquest and settlement, and they've really had to fight to keep their traditions alive. And so I think for Rina, this felt like one more way that changes were being forced onto the community.\n", + "\n", + "Roxanne Swentzell (37'55\"-38'7\"): I remember my mother being very troubled because it was just one more way the government was assimilating us into the American society.\n", + "\n", + "Delaney Hall (38'7\"-38'35\"): But of course, you know, to your point about the importance of affordable housing, yeah, that situation is complicated. Like in Santa Fe, there can be this obsession with traditional historic styles at the expense of just building out more affordable housing. But then in this Santa Clara example, there was affordable housing coming in that just didn't do enough to acknowledge traditional styles and practices when it comes to housing.\n", + "\n", + "Roman Mars (38'35\"-38'42\"): Yeah, there's just got to be this balance between building affordable housing and being sensitive to the local context, like everywhere.\n", + "\n", + "Delaney Hall (38'43\"-39'21\"): Right. And you know, it was interesting. There were affordable housing advocates I spoke to while I was researching this story who said, you know, in Santa Fe, if we're interested in building a community that is rooted in historical building practices, the Pueblos do have a lot to teach us. So there are some traditional Pueblo communities, for example, that are four or five stories tall. They're dense. They're multi-unit. And that kind of building is rare in Santa Fe, which is mostly built around the single-family, single-story model.\n", + "\n", + "Roman Mars (39'21\"-39'38\"): Wow. So, so basically the style of Pueblo architecture that Santa Fe sort of grabbed onto in the historic preservation was just this one really narrow slice of Adobe architecture. But there's so much more to learn from that they could be doing and, and creating dense housing.\n", + "\n", + "Delaney Hall (39'38\"-39'39\"): Yeah.\n", + "\n", + "Roman Mars (39'39\"-39'47\"): Yeah, definitely. So in the case of Santa Clara, did they eventually choose to include the HUD housing in their community?\n", + "\n", + "Delaney Hall (39'47\"-39'48\"): Yes, they did.\n", + "\n", + "Roman Mars (39'48\"-39'51\"): And how did it affect the Pueblo? Like what is it like these days?\n", + "\n", + "Delaney Hall (39'51\"-39'59\"): Yeah, I asked Roxanne about that and she said the center of the village still has its old adobe buildings.\n", + "\n", + "Roxanne Swentzell (39'59\"-40'23\"): But the middle of the village has emptied out of a lot of people. It's kind of like a ghost town of sorts and it only gets filled up on feast days or certain occasions. few houses that have people in, but most of the people have moved out to the suburbs. So it broke, it fragmented.\n", + "\n", + "Delaney Hall (40'23\"-40'55\"): But Roxanne says on the positive side, there's been a resurgence of interest in traditional adobe building techniques, and she actually teaches workshops on adobe construction. And she really credits her mom with giving her that sense of possibility when it comes to building. When we were talking, she told me this great story about how her first major building project was this family home that she built with her mom and dad. And she was a young teenager. She was in junior high.\n", + "\n", + "Roxanne Swentzell (40'55\"-41'20\"): I got to build my own bedroom. And I'm a little kid and I got to make my own bedroom. So I built me a stairway up to a bed. that had a neat pattern that went up around it and the stairs were goofy, but they worked, but I could make my own room. I'm so grateful that they gave me the knowing that you can.\n", + "\n", + "Delaney Hall (41'20\"-41'34\"): And so, you know, it's kind of that sense of possibility that she got from her mom. You know, that's what she wants to give other people in the Pueblo, that there's this very long tradition of building there and that, you know, they can do this.\n", + "\n", + "Roman Mars (41'35\"-41'40\"): Wow, that is so cool. Well, thanks so much, Delaney. I really appreciate you bringing this little extra part of the story to us.\n", + "\n", + "Delaney Hall (41'40\"-41'41\"): Yeah, yeah. Thank you.\n", + "\n", + "Roman Mars (41'47\"-43'29\"): 99% Invisible was produced this week by our senior producer Delaney Hall. Edited by Emmett Fitzgerald and Katie Mingle. Mixed by Bryson Barnes. Fact-checking by Francis Carr Jr. Music by Sean Real. Kurt Kolstad is the digital director. The rest of the team is Joe Rosenberg, Vivian Leigh, Christopher Johnson, Abby Madon, Chris Berube, Sophia Klatsker, and me, Roman Mars. Special thanks this week to Daniel Werwath, Rose Simpson, and the Archives of American Art at the Smithsonian Institution for the John Gall Meme Oral History Interview, which was conducted on December 3, 1964. Thanks also to Audra Belmore, the curator of the John Gall Meme Archives of Southwestern Architecture at UNM. Finally, special thanks to the Historic Division's partners in the study they conducted. They include New Mexico Health Equity Partnership, Historian and Preservation Planner John Murphy, Six Blooms, and Little Globe Inc. Little Globe has been conducting interviews with people in Santa Fe's Historic District and helped connect us with Ray Herrera. We are a project of 91.7 KALW in San Francisco and produced on Radio Row, which exists in various corners of North America, but in its heart will always be in beautiful downtown Oakland, California. We are a member of Radiotopia from PRX, a collective of the best, most innovative shows in all of podcasting. Discover, listen, and support them all at radiotopia.fm. You can find the show and join discussions about the show on Facebook. You can tweet me at Roman Mars and the show at 99pi.org. We're on Instagram and Reddit too. You like pictures of buildings made of mud? Well, I certainly do. And we got a bunch of them at 99pi.org.\n", + "\n", + "FROM NEWS CLIP (43'40\"-43'44\"): Radiotopia from PRX.\n", + "\n" + ] + } + ], + "source": [ + "# Let's combine the entries.\n", + "import copy\n", + "\n", + "def combine_same_speaker(result):\n", + " combined = [copy.copy(result[0])]\n", + " for r in result[1:]:\n", + " if r['speaker'] == combined[-1]['speaker']:\n", + " combined[-1]['end'] = r['end']\n", + " combined[-1]['text'] += \" \" + r['text'].strip()\n", + " combined[-1]['words'] += r['words']\n", + " else:\n", + " # Note: don't add r directly. Do a copy.\n", + " combined.append(copy.copy(r))\n", + " return combined\n", + "\n", + "combined = combine_same_speaker(result)\n", + "for r in combined:\n", + " start = format_seconds(r['start'])\n", + " end = format_seconds(r['end'])\n", + " print(f\"{speaker_names[r['speaker']]} ({start}-{end}): {r['text'].strip()}\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "fa8c7f39-f207-45ab-bd19-458d9628ce51", + "metadata": {}, + "source": [ + "Now, how do the interactions look like? Are the host and guests engaging in active conversations? One thing we can do is to print out a second-by-second conversation history, and visualize the whole 45-minute conversation as an image. Let's do that. If you are a python matplotlib fan, read the following code; otherwise, you can safely jump over and look at the generated image directly." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "b5e576b2", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Let's draw out the speaker map.\n", + "# Create a grid layout with two columns\n", + "from matplotlib import pyplot as plt\n", + "from matplotlib import colormaps\n", + "from matplotlib import gridspec\n", + "import numpy as np\n", + "import random\n", + "\n", + "def generate_colors(num_colors):\n", + " colormap = colormaps[\"Set3\"]\n", + " pastel_colors = [colormap(i) for i in range(num_colors)]\n", + " random.shuffle(pastel_colors)\n", + " return pastel_colors\n", + "\n", + "color_map = {\n", + " s:c[:3] for s, c in zip(real_speakers, generate_colors(len(real_speakers)))\n", + "}\n", + "\n", + "\n", + "\n", + "total_time = int(combined[-1]['end'] // 60 + 1) * 60\n", + "colored_timelapse = np.ones((total_time, 3))\n", + "for r in result:\n", + " start = int(r['start'])\n", + " end = int(r['end'] + 0.5)\n", + " colored_timelapse[start:end] = color_map[speaker_names[r['speaker']]]\n", + " \n", + "fig = plt.figure(figsize=(8, 4))\n", + "gs = gridspec.GridSpec(1, 2, width_ratios=[3, 1])\n", + "\n", + "# Add the image to the left grid cell\n", + "ax_image = plt.subplot(gs[0])\n", + "ax_image.imshow(colored_timelapse.reshape((total_time//60, 60,3)))\n", + "plt.xlabel(\"seconds\")\n", + "plt.ylabel(\"minutes\")\n", + "\n", + "# Add the legend to the right grid cell\n", + "legend_patches = [plt.Line2D([0], [0], marker='o', color='w', label=speaker, \n", + " markersize=10, markerfacecolor=color)\n", + " for speaker, color in sorted(color_map.items(), key=lambda x: x[0])]\n", + "ax_legend = plt.subplot(gs[1])\n", + "ax_legend.legend(handles=legend_patches, loc='upper left')\n", + "ax_legend.axis('off')\n", + "\n", + "plt.tight_layout()\n", + "\n", + "# Display the figure\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "bf4ac95c", + "metadata": {}, + "source": [ + "To read the above figure: every horizontal row represents 60 seconds of a minute, and there are 43 rows representing 43 minutes' time. Every color represents a speaker: for example, for the first minute, you see Roman Mars speaking for about 20 seconds, then Trey Jordan, then Roman, then Trey, and then Delaney Hall. White space shows pauses where no one speaks.\n", + "\n", + "A few observations from the color map:\n", + "- Roman Mars opens and ends the conversation as the host.\n", + "- Denaley Hall co-hosts the converation, and speaks most frequently - connecting the dots among guests.\n", + "- Trey joins the first part of the conversation; Chris joins later; Joseph, Lisa and Ray engages the conversation between 15' and 30'. After the break around 29', Roxanne and Delaney had an in-depth discussion for about 10 minutes, before the conversation comes to conclusion.\n", + "\n", + "Overall the audiences had a very active engagement - lots of discussions, and also in-depth statements especially in the second half of the conversation.\n", + "\n", + "Back to our technical story - it used to be difficult to have custom AI models deployed easily, and data scientists need to spend a lot of time dealing with infra before interesting work like conversation analysis can begin. Lepton aims to change this.\n", + "\n", + "# Conclusion\n", + "\n", + "Speech recognition and speech diarization are common techniques in the speech field. Combining these AI algorithms with a bit of data science could give us interesting insights into our multimedia data. \n", + "\n", + "We want AI algorithms and applications to be customizable, highly efficient, and easy to use. Let us know what you think! Feel free to ping us at [info@lepton.ai](mailto:info@lepton.ai) any time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd0d8860", + "metadata": {}, + "outputs": [], + "source": [ + "# Let's close the service after done.\n", + "!lep deployment remove -n whisperx\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/advanced/whisperx/whisperx_background_job.py b/advanced/whisperx/whisperx_background_job.py new file mode 100644 index 0000000..09edbf3 --- /dev/null +++ b/advanced/whisperx/whisperx_background_job.py @@ -0,0 +1,296 @@ +import json +import os +import sys +import time +from typing import Dict, Optional +import uuid + +from leptonai.photon import Photon, FileParam, HTTPException +from loguru import logger +import whisperx + + +class WhisperXBackground(Photon): + """ + A WhisperX photon that serves the [WhisperX](https://github.com/m-bain/whisperX) model. + + The photon exposes two endpoints: `/run` and `/run_upload` that deals with files/urls + and uploaded contents respectively. See the docs of each for details. + + Different from the main WhisperX photon, this photon starts background tassks in the + background, so it handles requests more efficiently. For example, for the main photon, + if you run a prediction, it will block the server until the prediction is done, giving + a pretty bad user experience. This photon, on the other hand, will return immediately + with a task id. The user can then use the task id to query the status of the task, and + get the result when it is done. + """ + + requirement_dependency = [ + "leptonai", + "torch", + "torchaudio", + "git+https://github.com/m-bain/whisperx.git", + ] + + system_dependencies = ["ffmpeg"] + + # Parameters for the photon. + # The photon will need to have a storage folder + OUTPUT_ROOT = os.environ.get("WHISPERX_OUTPUT_ROOT", "/tmp/whisperx") + JOB_FILE_EXTENSION = ".input" + OUTPUT_FILE_EXTENSION = ".json" + OUTPUT_MAXIMUM_AGE = 60 * 60 * 24 # 1 day + CLEANUP_INTERVAL = 60 * 60 # 1 hour + LAST_CLEANUP_TIME = time.time() + + def init(self): + logger.info("Initializing WhisperXPhoton") + + # 0. Create output root, and launch a thread to clean up old files + os.makedirs(self.OUTPUT_ROOT, exist_ok=True) + + # 1. Load whisper model + self.hf_token = os.environ.get("HUGGING_FACE_HUB_TOKEN", None) + if not self.hf_token: + logger.error("Please set the environment variable HUGGING_FACE_HUB_TOKEN.") + sys.exit(1) + self.device = "cuda" + compute_type = "float16" + self._model = whisperx.load_model( + "large-v2", self.device, compute_type=compute_type + ) + + self._language_code = "en" + # 2. load whisper align model + model_a, metadata = whisperx.load_align_model( + language_code=self._language_code, device=self.device + ) + self._diarize_model = whisperx.DiarizationPipeline( + use_auth_token=self.hf_token, device=self.device + ) + + def _gen_unique_filename(self) -> str: + return str(uuid.uuid4()) + + def _regular_clean_up(self): + if time.time() - self.LAST_CLEANUP_TIME < self.CLEANUP_INTERVAL: + return + logger.info(f"Cleaning up {self.OUTPUT_ROOT} regularly") + self.LAST_CLEANUP_TIME = time.time() + for filename in os.listdir(self.OUTPUT_ROOT): + if filename.endswith(self.OUTPUT_FILE_EXTENSION): + filepath = os.path.join(self.OUTPUT_ROOT, filename) + # Checks if files are older than 1 hour. If so, delete them. + if ( + os.path.isfile(filepath) + and time.time() - os.path.getmtime(filepath) + > self.OUTPUT_MAXIMUM_AGE + ): + os.remove(filepath) + + def _run_file_or_url( + self, + audio_file_or_url: str, + output_filename: str, + batch_size: int = 4, + min_speakers: Optional[int] = None, + max_speakers: Optional[int] = None, + ) -> None: + """ + The main function that is called by the others. + """ + output_filepath = os.path.join(self.OUTPUT_ROOT, output_filename) + try: + audio = whisperx.load_audio(audio_file_or_url) + except Exception as e: + errormsg = ( + f"Cannot load audio at {audio_file_or_url}. Detailed error message:" + f" {str(e)}" + ) + json.dump({"error": errormsg}, open(output_filepath, "w")) + return + + result = self._model.transcribe(audio, batch_size=batch_size) + # print(result["segments"]) # before alignment + + if self._language_code != result["language"]: + self._model_a, self._metadata = whisperx.load_align_model( + language_code=result["language"], device=self.device + ) + self._language_code = result["language"] + + # 2. Align whisper output + model_a, metadata = whisperx.load_align_model( + language_code=result["language"], device=self.device + ) + result = whisperx.align( + result["segments"], + model_a, + metadata, + audio, + self.device, + return_char_alignments=False, + ) + # print(result["segments"]) # after alignment + + # add min/max number of speakers if known + if ( + min_speakers + and max_speakers + and min_speakers <= max_speakers + and min_speakers > 0 + ): + diarize_segments = self._diarize_model( + audio, min_speakers=min_speakers, max_speakers=max_speakers + ) + else: + # ignore the hint and do diarization. + diarize_segments = self._diarize_model(audio) + + result = whisperx.assign_word_speakers(diarize_segments, result) + # return result["segments"] # segments are now assigned speaker IDs + json.dump(result["segments"], open(output_filepath, "w")) + # If it is a local file, remove it + if audio_file_or_url.startswith(self.OUTPUT_ROOT): + os.remove(audio_file_or_url) + return + + @Photon.handler( + example={ + "filename": ( + "https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/1.flac" + ), + } + ) + def run( + self, + filename: str, + batch_size: int = 4, + min_speakers: Optional[int] = None, + max_speakers: Optional[int] = None, + ) -> Dict[str, str]: + """ + Runs transcription, alignment, and diarization for the input. + + - Inputs: + - filename: a url containing the audio file, or a local file path if running + locally. + - batch_size(optional): the batch size to run whisperx inference. + - min_speakers(optional): the hint for minimum number of speakers for diarization. + - max_speakers(optional): the hint for maximum number of speakers for diarization. + + - Returns: + - task: a dictionary with key `task_id` and value the task uuid. Use `status(**task)` + to query the task status, and `get_result(**task)` to get the result when the + status is "ok". + """ + unique_name = self._gen_unique_filename() + self.add_background_task( + self._run_file_or_url, + filename, + unique_name + self.OUTPUT_FILE_EXTENSION, + batch_size, + min_speakers, + max_speakers, + ) + self._regular_clean_up() + return {"task_id": unique_name} + + @Photon.handler( + example={ + "upload_file": ( + "(please use python) FileParam(open('path/to/your/file.wav', 'rb'))" + ), + } + ) + def run_upload( + self, + upload_file: FileParam, + batch_size: int = 4, + min_speakers: Optional[int] = None, + max_speakers: Optional[int] = None, + ) -> Dict[str, str]: + """ + Runs transcription, alignment, and diarization for the input. + + Everything is the same as the `/run` path, except that the input is uploaded + as a file. If you are using the lepton python client, you can achieve so by + from leptonai.photon import FileParam + from leptonai.client import Client + client = Client(PUT_YOUR_SERVER_INFO_HERE) + client.run_upload(upload_file=FileParam(open("path/to/your/file.wav", "rb"))) + + For more details, refer to `/run`. + """ + unique_name = self._gen_unique_filename() + task_file = os.path.join( + self.OUTPUT_ROOT, unique_name + self.JOB_FILE_EXTENSION + ) + with open(task_file, "wb") as f: + f.write(upload_file.file.read()) + f.flush() + self.add_background_task( + self._run_file_or_url, + task_file, + unique_name + self.OUTPUT_FILE_EXTENSION, + batch_size, + min_speakers, + max_speakers, + ) + self._regular_clean_up() + return {"task_id": unique_name} + + @Photon.handler + def status(self, task_id: str) -> Dict[str, str]: + """ + Returns the status of the task. It could be "invalid_task_id", "pending", "not_found", or "ok". + """ + try: + _ = uuid.UUID(task_id, version=4) + except ValueError: + return {"status": "invalid_task_id"} + input_filepath = os.path.join( + self.OUTPUT_ROOT, task_id + self.JOB_FILE_EXTENSION + ) + output_filepath = os.path.join( + self.OUTPUT_ROOT, task_id + self.OUTPUT_FILE_EXTENSION + ) + if not os.path.exists(output_filepath): + if os.path.exists(input_filepath): + return {"status": "pending"} + else: + return {"status": "not_found"} + else: + return {"status": "ok"} + + @Photon.handler + def get_result(self, task_id: str) -> Dict: + """ + Gets the result of the whisper x task. If the task is not finished, it will raise a 404 error. + Use `status(task_id=task_id)` to check if the task is finished. + """ + if self.status(task_id=task_id)["status"] == "ok": + output_filepath = os.path.join( + self.OUTPUT_ROOT, task_id + self.OUTPUT_FILE_EXTENSION + ) + return json.load(open(output_filepath, "r")) + else: + raise HTTPException(status_code=404, detail="result not found") + + @Photon.handler + def queue_length(self) -> int: + """ + Returns the current queue length. + """ + return len( + [ + f + for f in os.listdir(self.OUTPUT_ROOT) + if f.endswith(self.JOB_FILE_EXTENSION) + ] + ) + + +if __name__ == "__main__": + p = WhisperXBackground() + p.launch()