[{"data":1,"prerenderedAt":1352},["ShallowReactive",2],{"article-azure-appservices-containersapps":3},{"article":4,"tags":415,"previous":430,"next":980},{"id":5,"title":6,"author":7,"body":8,"createdAt":403,"description":404,"extension":405,"img":406,"meta":407,"navigation":408,"path":409,"seo":410,"stem":411,"tags":412,"updatedAt":403,"__hash__":414},"articles\u002Farticles\u002Fazure-appservices-containersapps.md","Comparing Azure App Services and Azure Container Apps Features Benefits Pros and Cons",null,{"type":9,"value":10,"toc":392},"minimark",[11,16,20,26,29,31,35,42,47,81,86,112,117,137,141,146,150,182,186,211,215,235,239,245,251,255,258,373,375,379,384,389],[12,13,15],"h3",{"id":14},"comparing-azure-app-services-and-azure-container-apps-features-benefits-pros-and-cons","Comparing Azure App Services and Azure Container Apps: Features, Benefits, Pros, and Cons",[17,18,19],"p",{},"When deploying and managing applications on Azure, two prominent options stand out: Azure App Services and Azure Container Apps. Both cater to different use cases and offer distinct features. Here, we'll dive into their differences, benefits, pros, and cons, and examine their performance features.",[21,22],"img",{"style":23,"src":24,"alt":25,"title":25},"display: inline;","\u002Farticles\u002Fimages\u002Fappservices_vs_containerapps_2.png","image",[27,28],"br",{},[27,30],{},[12,32,34],{"id":33},"azure-app-services","Azure App Services",[17,36,37,41],{},[38,39,40],"strong",{},"Overview:","\nAzure App Services is a platform-as-a-service (PaaS) offering that allows developers to build, deploy, and scale web apps, mobile backends, and RESTful APIs.",[17,43,44],{},[38,45,46],{},"Benefits:",[48,49,50,57,63,69,75],"ul",{},[51,52,53,56],"li",{},[38,54,55],{},"Managed Environment:"," Handles infrastructure management, including patching and scaling.",[51,58,59,62],{},[38,60,61],{},"Integrated Development Environment:"," Supports multiple languages and frameworks like .NET, Java, Node.js, PHP, Python, and Ruby.",[51,64,65,68],{},[38,66,67],{},"Deployment Options:"," Facilitates continuous integration and deployment with GitHub, Azure DevOps, and other CI\u002FCD tools.",[51,70,71,74],{},[38,72,73],{},"Built-in Services:"," Includes load balancing, auto-scaling, and built-in monitoring and diagnostics.",[51,76,77,80],{},[38,78,79],{},"Security:"," Offers SSL certificates, custom domain names, and compliance with industry standards.",[17,82,83],{},[38,84,85],{},"Pros:",[48,87,88,94,100,106],{},[51,89,90,93],{},[38,91,92],{},"Ease of Use:"," Simplified deployment and management with minimal configuration.",[51,95,96,99],{},[38,97,98],{},"Scalability:"," Automatically scales up or out based on demand.",[51,101,102,105],{},[38,103,104],{},"Integration:"," Seamless integration with other Azure services (e.g., Azure SQL Database, Azure Storage).",[51,107,108,111],{},[38,109,110],{},"Cost Management:"," Flexible pricing plans, including a free tier for basic apps.",[17,113,114],{},[38,115,116],{},"Cons:",[48,118,119,125,131],{},[51,120,121,124],{},[38,122,123],{},"Limited Customization:"," Limited control over the underlying infrastructure.",[51,126,127,130],{},[38,128,129],{},"Dependency on Azure Ecosystem:"," Strongly tied to Azure services, which might be a drawback for multi-cloud strategies.",[51,132,133,136],{},[38,134,135],{},"Complexity in Advanced Scenarios:"," May require workarounds or additional services for complex scenarios like multi-region deployments or specific compliance requirements.",[12,138,140],{"id":139},"azure-container-apps","Azure Container Apps",[17,142,143,145],{},[38,144,40],{},"\nAzure Container Apps is a serverless container service designed to build and deploy modern applications using microservices and container orchestration.",[17,147,148],{},[38,149,46],{},[48,151,152,158,164,170,176],{},[51,153,154,157],{},[38,155,156],{},"Serverless:"," Abstracts the underlying infrastructure, allowing developers to focus on application logic.",[51,159,160,163],{},[38,161,162],{},"Microservices Support:"," Ideal for deploying applications composed of multiple microservices.",[51,165,166,169],{},[38,167,168],{},"Flexibility:"," Supports any containerized application, irrespective of the programming language or framework.",[51,171,172,175],{},[38,173,174],{},"Event-driven Architecture:"," Integrates with Azure Event Grid, Azure Functions, and other event-driven services.",[51,177,178,181],{},[38,179,180],{},"Auto-scaling:"," Automatically scales based on HTTP traffic or custom metrics.",[17,183,184],{},[38,185,85],{},[48,187,188,194,200,205],{},[51,189,190,193],{},[38,191,192],{},"Agility:"," Quick to deploy and update containerized applications.",[51,195,196,199],{},[38,197,198],{},"Granular Control:"," More control over the runtime environment compared to App Services.",[51,201,202,204],{},[38,203,98],{}," Efficient scaling at the container level, supporting spikes in demand.",[51,206,207,210],{},[38,208,209],{},"Portability:"," Containers can be moved across different environments, including on-premises and other cloud providers.",[17,212,213],{},[38,214,116],{},[48,216,217,223,229],{},[51,218,219,222],{},[38,220,221],{},"Complexity:"," Requires understanding of containerization and orchestration concepts.",[51,224,225,228],{},[38,226,227],{},"Cold Start Latency:"," Potential cold start issues similar to other serverless offerings.",[51,230,231,234],{},[38,232,233],{},"Resource Management:"," Although managed, you still need to handle aspects like container lifecycle and resource optimization.",[12,236,238],{"id":237},"performance-features-comparison","Performance Features Comparison",[17,240,241,242,244],{},"When comparing performance features, Azure App Services and Azure Container Apps offer distinct capabilities tailored to their respective use cases. ",[38,243,34],{}," provides performance optimization through automatic scaling, load balancing, and built-in caching mechanisms. It supports scaling both vertically (increasing the power of existing instances) and horizontally (adding more instances) based on predefined metrics or schedules. App Services also integrates seamlessly with Azure CDN for improved global performance and Azure Traffic Manager for efficient traffic distribution.",[17,246,247,248,250],{},"In contrast, ",[38,249,140],{}," leverages Kubernetes-based orchestration under the hood, offering granular control over performance tuning. It excels in handling microservices architectures, allowing individual containers to scale independently based on specific metrics, such as CPU and memory usage. This fine-grained scaling ensures optimal resource utilization and performance efficiency for each microservice. Container Apps also support advanced networking features, such as service mesh integration, which enhances performance by optimizing service-to-service communication within the application.",[12,252,254],{"id":253},"when-to-use-each-service","When to Use Each Service",[17,256,257],{},"Here's a table summarizing when each service is well suited:",[259,260,261,281],"table",{},[262,263,264],"thead",{},[265,266,267,273,277],"tr",{},[268,269,270],"th",{},[38,271,272],{},"Scenario",[268,274,275],{},[38,276,34],{},[268,278,279],{},[38,280,140],{},[282,283,284,296,307,318,329,340,351,362],"tbody",{},[265,285,286,290,293],{},[287,288,289],"td",{},"Traditional web apps and APIs",[287,291,292],{},"Best suited for simple, monolithic applications",[287,294,295],{},"Not ideal",[265,297,298,301,304],{},[287,299,300],{},"Rapid development and deployment",[287,302,303],{},"Excellent choice with easy CI\u002FCD integration",[287,305,306],{},"Suitable, but requires container knowledge",[265,308,309,312,315],{},[287,310,311],{},"Minimal infrastructure management",[287,313,314],{},"Ideal, as it abstracts infrastructure complexities",[287,316,317],{},"Provides some abstraction, but requires container management",[265,319,320,323,326],{},[287,321,322],{},"Applications with predictable traffic",[287,324,325],{},"Handles predictable scaling efficiently",[287,327,328],{},"Handles scaling well, but shines with fluctuating workloads",[265,330,331,334,337],{},[287,332,333],{},"Microservices architecture",[287,335,336],{},"Not optimized for microservices",[287,338,339],{},"Perfectly suited for microservices",[265,341,342,345,348],{},[287,343,344],{},"Granular performance tuning",[287,346,347],{},"Limited to platform capabilities",[287,349,350],{},"Offers fine-grained control and optimization",[265,352,353,356,359],{},[287,354,355],{},"Multi-cloud and portability needs",[287,357,358],{},"Tightly integrated with Azure ecosystem",[287,360,361],{},"Highly portable across different environments",[265,363,364,367,370],{},[287,365,366],{},"Event-driven applications",[287,368,369],{},"Can be integrated with event-driven services",[287,371,372],{},"Natively supports event-driven architectures",[27,374],{},[12,376,378],{"id":377},"conclusion","Conclusion",[17,380,381,383],{},[38,382,34],{}," is best for developers looking for a straightforward way to deploy web apps and APIs without worrying about infrastructure management. It's ideal for traditional web applications that require a quick and easy deployment process.",[17,385,386,388],{},[38,387,140],{}," is suited for developers who need more control over their application environment and want to deploy modern, containerized applications with microservices architecture. It offers greater flexibility and is more suitable for complex applications requiring fine-grained scaling and orchestration.",[17,390,391],{},"Choosing between the two depends on your application's architecture, your team's expertise with containers, and your need for control versus ease of use. Whether you prioritize the simplicity and integrated services of App Services or the granular control and performance optimization of Container Apps, Azure has a solution to meet your needs.",{"title":393,"searchDepth":394,"depth":394,"links":395},"",2,[396,398,399,400,401,402],{"id":14,"depth":397,"text":15},3,{"id":33,"depth":397,"text":34},{"id":139,"depth":397,"text":140},{"id":237,"depth":397,"text":238},{"id":253,"depth":397,"text":254},{"id":377,"depth":397,"text":378},"2024-06-12T15:44:03.462Z","When deploying and managing applications on Azure, two prominent options stand out. Azure App Services and Azure Container Apps. Both cater to different use cases and offer distinct features. Here, we'll dive into their differences, benefits, pros, and cons, and examine their performance features.","md","\u002Farticles\u002Fimages\u002Fappservices_vs_containerapps.png",{},true,"\u002Farticles\u002Fazure-appservices-containersapps",{"title":6,"description":404},"articles\u002Fazure-appservices-containersapps",[413],"azure","gXbVnG9BGDl9U618t6qtPPrPHpfcxpLl8gKn_ydmDbI",[416],{"id":417,"title":418,"body":419,"description":423,"extension":405,"img":424,"meta":425,"name":413,"navigation":408,"path":426,"seo":427,"stem":428,"__hash__":429},"tags\u002Ftags\u002Fazure.md","Azure",{"type":9,"value":420,"toc":421},[],{"title":393,"searchDepth":394,"depth":394,"links":422},[],"Azure cloud platform is more than 200 products and cloud services designed to help you bring new solutions to life","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1598313183973-4effcded8d5e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=675&q=80",{},"\u002Ftags\u002Fazure",{"description":423},"tags\u002Fazure","m01ax_ShM5MuWl7UByoMyql_zrDRu_4udP4MyD4fL-k",{"id":431,"title":432,"author":7,"body":433,"createdAt":970,"description":971,"extension":405,"img":972,"meta":973,"navigation":408,"path":974,"seo":975,"stem":976,"tags":977,"updatedAt":970,"__hash__":979},"articles\u002Farticles\u002Fgoogletakeout-extract-script.md","Extracting Specific Files from Zip Archives with a Python Script",{"type":9,"value":434,"toc":962},[435,438,441,444,447,449,451,455,475,479,482,801,805,879,883,898,927,934,950,953,955,958],[12,436,432],{"id":437},"extracting-specific-files-from-zip-archives-with-a-python-script",[17,439,440],{},"When managing large amounts of data, especially backups from services like Google Photos, you may find yourself dealing with numerous zip files. Manually extracting specific files from these archives can be tedious. Fortunately, Python offers a powerful way to automate this process.",[17,442,443],{},"In this blog post, I'll show you how to create a Python script that extracts files from zip archives to a specific path on your hard drive. You can specify a particular path within each zip file to extract files from, making it ideal for organizing photos or other data from Google backups.  The script below will iterate over each zip file within\nthe directory and perform the same extraction from within each zip to another target directory.  In our particular case we had 17 - 10 gb zip files and we need to iterate over each to extract the photos.",[21,445],{"style":23,"src":446,"alt":25,"title":25},"\u002Farticles\u002Fimages\u002Fpythonscript.jpg",[27,448],{},[27,450],{},[12,452,454],{"id":453},"prerequisites","Prerequisites",[17,456,457,458,465,466,470,471,474],{},"Before we dive into the script, ensure you have Python installed on your machine. You can download it from ",[459,460,464],"a",{"href":461,"rel":462},"https:\u002F\u002Fwww.python.org\u002F",[463],"nofollow","python.org",". You'll also need the ",[467,468,469],"code",{},"zipfile"," and ",[467,472,473],{},"os"," modules, which are part of Python's standard library, so no additional installations are required.",[12,476,478],{"id":477},"the-script","The Script",[17,480,481],{},"Here's the Python script to extract files from zip archives:",[483,484,488],"pre",{"className":485,"code":486,"language":487,"meta":393,"style":393},"language-python shiki shiki-themes github-light github-dark","import os\nimport zipfile\n\ndef extract_specific_path_from_zip(source_dir, dest_dir, specific_path):\n    # Ensure destination directory exists\n    if not os.path.exists(dest_dir):\n        os.makedirs(dest_dir)\n    \n    # Loop through all files in the source directory\n    for item in os.listdir(source_dir):\n        # Construct full file path\n        file_path = os.path.join(source_dir, item)\n        \n        # Check if the file is a ZIP file\n        if zipfile.is_zipfile(file_path):\n            # Open the ZIP file\n            with zipfile.ZipFile(file_path, 'r') as zip_ref:\n                # Get the list of all archived file names from the zip\n                zip_file_names = zip_ref.namelist()\n                \n                # Filter the files that match the specific path\n                files_to_extract = [f for f in zip_file_names if f.startswith(specific_path)]\n                \n                # Extract the filtered files preserving the directory structure below the specific path\n                for file in files_to_extract:\n                    try:\n                        # Determine the relative path within the specific path\n                        relative_path = os.path.relpath(file, specific_path)\n                        \n                        # Determine the output file path\n                        output_file_path = os.path.join(dest_dir, relative_path)\n                        \n                        # Normalize the output file path to handle any issues with invalid characters or spaces\n                        output_file_path = os.path.normpath(output_file_path)\n                        \n                        # Ensure the directory exists\n                        os.makedirs(os.path.dirname(output_file_path), exist_ok=True)\n                        \n                        # Extract the file data and write to the destination directory\n                        with zip_ref.open(file) as source_file:\n                            with open(output_file_path, 'wb') as output_file:\n                                output_file.write(source_file.read())\n                        \n                        print(f\"Extracted: {file} from {file_path} to {output_file_path}\")\n                    except Exception as e:\n                        print(f\"Failed to extract {file} from {file_path}. Error: {e}\")\n\nif __name__ == \"__main__\":\n    source_directory = \"C:\u002FTemp\u002FMay23_BrittmarieGoogleBackup\"  # Replace with the path to the source directory\n    destination_directory = \"G:\u002FHome_PC\u002FPictures\u002F2023-06-23\"  # Replace with the path to the destination directory\n    specific_path_in_zip = \"Takeout\u002FGoogle Photos\"  # Replace with the specific path to extract from each ZIP file\n\n    extract_specific_path_from_zip(source_directory, destination_directory, specific_path_in_zip)\n","python",[467,489,490,498,503,508,514,520,526,532,538,544,550,556,562,568,574,580,586,592,598,604,610,616,622,627,633,639,645,651,657,663,669,675,680,686,692,697,703,709,714,720,726,732,738,743,749,755,761,766,772,778,784,790,795],{"__ignoreMap":393},[491,492,495],"span",{"class":493,"line":494},"line",1,[491,496,497],{},"import os\n",[491,499,500],{"class":493,"line":394},[491,501,502],{},"import zipfile\n",[491,504,505],{"class":493,"line":397},[491,506,507],{"emptyLinePlaceholder":408},"\n",[491,509,511],{"class":493,"line":510},4,[491,512,513],{},"def extract_specific_path_from_zip(source_dir, dest_dir, specific_path):\n",[491,515,517],{"class":493,"line":516},5,[491,518,519],{},"    # Ensure destination directory exists\n",[491,521,523],{"class":493,"line":522},6,[491,524,525],{},"    if not os.path.exists(dest_dir):\n",[491,527,529],{"class":493,"line":528},7,[491,530,531],{},"        os.makedirs(dest_dir)\n",[491,533,535],{"class":493,"line":534},8,[491,536,537],{},"    \n",[491,539,541],{"class":493,"line":540},9,[491,542,543],{},"    # Loop through all files in the source directory\n",[491,545,547],{"class":493,"line":546},10,[491,548,549],{},"    for item in os.listdir(source_dir):\n",[491,551,553],{"class":493,"line":552},11,[491,554,555],{},"        # Construct full file path\n",[491,557,559],{"class":493,"line":558},12,[491,560,561],{},"        file_path = os.path.join(source_dir, item)\n",[491,563,565],{"class":493,"line":564},13,[491,566,567],{},"        \n",[491,569,571],{"class":493,"line":570},14,[491,572,573],{},"        # Check if the file is a ZIP file\n",[491,575,577],{"class":493,"line":576},15,[491,578,579],{},"        if zipfile.is_zipfile(file_path):\n",[491,581,583],{"class":493,"line":582},16,[491,584,585],{},"            # Open the ZIP file\n",[491,587,589],{"class":493,"line":588},17,[491,590,591],{},"            with zipfile.ZipFile(file_path, 'r') as zip_ref:\n",[491,593,595],{"class":493,"line":594},18,[491,596,597],{},"                # Get the list of all archived file names from the zip\n",[491,599,601],{"class":493,"line":600},19,[491,602,603],{},"                zip_file_names = zip_ref.namelist()\n",[491,605,607],{"class":493,"line":606},20,[491,608,609],{},"                \n",[491,611,613],{"class":493,"line":612},21,[491,614,615],{},"                # Filter the files that match the specific path\n",[491,617,619],{"class":493,"line":618},22,[491,620,621],{},"                files_to_extract = [f for f in zip_file_names if f.startswith(specific_path)]\n",[491,623,625],{"class":493,"line":624},23,[491,626,609],{},[491,628,630],{"class":493,"line":629},24,[491,631,632],{},"                # Extract the filtered files preserving the directory structure below the specific path\n",[491,634,636],{"class":493,"line":635},25,[491,637,638],{},"                for file in files_to_extract:\n",[491,640,642],{"class":493,"line":641},26,[491,643,644],{},"                    try:\n",[491,646,648],{"class":493,"line":647},27,[491,649,650],{},"                        # Determine the relative path within the specific path\n",[491,652,654],{"class":493,"line":653},28,[491,655,656],{},"                        relative_path = os.path.relpath(file, specific_path)\n",[491,658,660],{"class":493,"line":659},29,[491,661,662],{},"                        \n",[491,664,666],{"class":493,"line":665},30,[491,667,668],{},"                        # Determine the output file path\n",[491,670,672],{"class":493,"line":671},31,[491,673,674],{},"                        output_file_path = os.path.join(dest_dir, relative_path)\n",[491,676,678],{"class":493,"line":677},32,[491,679,662],{},[491,681,683],{"class":493,"line":682},33,[491,684,685],{},"                        # Normalize the output file path to handle any issues with invalid characters or spaces\n",[491,687,689],{"class":493,"line":688},34,[491,690,691],{},"                        output_file_path = os.path.normpath(output_file_path)\n",[491,693,695],{"class":493,"line":694},35,[491,696,662],{},[491,698,700],{"class":493,"line":699},36,[491,701,702],{},"                        # Ensure the directory exists\n",[491,704,706],{"class":493,"line":705},37,[491,707,708],{},"                        os.makedirs(os.path.dirname(output_file_path), exist_ok=True)\n",[491,710,712],{"class":493,"line":711},38,[491,713,662],{},[491,715,717],{"class":493,"line":716},39,[491,718,719],{},"                        # Extract the file data and write to the destination directory\n",[491,721,723],{"class":493,"line":722},40,[491,724,725],{},"                        with zip_ref.open(file) as source_file:\n",[491,727,729],{"class":493,"line":728},41,[491,730,731],{},"                            with open(output_file_path, 'wb') as output_file:\n",[491,733,735],{"class":493,"line":734},42,[491,736,737],{},"                                output_file.write(source_file.read())\n",[491,739,741],{"class":493,"line":740},43,[491,742,662],{},[491,744,746],{"class":493,"line":745},44,[491,747,748],{},"                        print(f\"Extracted: {file} from {file_path} to {output_file_path}\")\n",[491,750,752],{"class":493,"line":751},45,[491,753,754],{},"                    except Exception as e:\n",[491,756,758],{"class":493,"line":757},46,[491,759,760],{},"                        print(f\"Failed to extract {file} from {file_path}. Error: {e}\")\n",[491,762,764],{"class":493,"line":763},47,[491,765,507],{"emptyLinePlaceholder":408},[491,767,769],{"class":493,"line":768},48,[491,770,771],{},"if __name__ == \"__main__\":\n",[491,773,775],{"class":493,"line":774},49,[491,776,777],{},"    source_directory = \"C:\u002FTemp\u002FMay23_BrittmarieGoogleBackup\"  # Replace with the path to the source directory\n",[491,779,781],{"class":493,"line":780},50,[491,782,783],{},"    destination_directory = \"G:\u002FHome_PC\u002FPictures\u002F2023-06-23\"  # Replace with the path to the destination directory\n",[491,785,787],{"class":493,"line":786},51,[491,788,789],{},"    specific_path_in_zip = \"Takeout\u002FGoogle Photos\"  # Replace with the specific path to extract from each ZIP file\n",[491,791,793],{"class":493,"line":792},52,[491,794,507],{"emptyLinePlaceholder":408},[491,796,798],{"class":493,"line":797},53,[491,799,800],{},"    extract_specific_path_from_zip(source_directory, destination_directory, specific_path_in_zip)\n",[12,802,804],{"id":803},"how-it-works","How It Works",[806,807,808,819,849,855,861,867,873],"ol",{},[51,809,810,813,814,470,816,818],{},[38,811,812],{},"Import Modules",": The script begins by importing the ",[467,815,469],{},[467,817,473],{}," modules.",[51,820,821,824,825,828,829],{},[38,822,823],{},"Function Definition",": The ",[467,826,827],{},"extract_specific_path_from_zip"," function takes three parameters:\n",[48,830,831,837,843],{},[51,832,833,836],{},[467,834,835],{},"source_dir",": The directory containing the zip files you want to extract files from.",[51,838,839,842],{},[467,840,841],{},"dest_dir",": The directory where you want the extracted files to be saved.",[51,844,845,848],{},[467,846,847],{},"specific_path",": The specific path within each zip file from which you want to extract files.",[51,850,851,854],{},[38,852,853],{},"Ensure Destination Directory Exists",": The script checks if the destination directory exists and creates it if necessary.",[51,856,857,860],{},[38,858,859],{},"Loop Through Source Directory",": It loops through all files in the source directory, checking each one to see if it's a zip file.",[51,862,863,866],{},[38,864,865],{},"Open Zip File",": For each zip file, the script opens it and lists all the files within the zip archive.",[51,868,869,872],{},[38,870,871],{},"Filter Files",": The script filters the files based on the specified path within the zip file.",[51,874,875,878],{},[38,876,877],{},"Extract Files",": For each filtered file, the script constructs the target file path, creates necessary directories, and writes the file to the target path, handling any issues with invalid characters or spaces.",[12,880,882],{"id":881},"usage","Usage",[17,884,885,886,889,890,893,894,897],{},"To use this script, replace the placeholder values for ",[467,887,888],{},"source_directory",", ",[467,891,892],{},"destination_directory",", and ",[467,895,896],{},"specific_path_in_zip"," with your specific paths. For example, if you want to extract all photos from a Google Photos backup, you might have:",[483,899,901],{"className":485,"code":900,"language":487,"meta":393,"style":393},"if __name__ == \"__main__\":\n    source_directory = \"C:\u002FTemp\u002FMay23_BrittmarieGoogleBackup\"  # Replace with the path to the source directory\n    destination_directory = \"G:\u002FHome_PC\u002FPictures\u002F2023-06-23\"  # Replace with the path to the destination directory\n    specific_path_in_zip = \"Takeout\u002FGoogle Photos\"  # Replace with the specific path to extract from each ZIP file\n\n    extract_specific_path_from_zip(source_directory, destination_directory, specific_path_in_zip)\n",[467,902,903,907,911,915,919,923],{"__ignoreMap":393},[491,904,905],{"class":493,"line":494},[491,906,771],{},[491,908,909],{"class":493,"line":394},[491,910,777],{},[491,912,913],{"class":493,"line":397},[491,914,783],{},[491,916,917],{"class":493,"line":510},[491,918,789],{},[491,920,921],{"class":493,"line":516},[491,922,507],{"emptyLinePlaceholder":408},[491,924,925],{"class":493,"line":522},[491,926,800],{},[17,928,929,930,933],{},"Save the script as ",[467,931,932],{},"extract_photos.py"," and run it using:",[483,935,939],{"className":936,"code":937,"language":938,"meta":393,"style":393},"language-bash shiki shiki-themes github-light github-dark","python extract_photos.py\n","bash",[467,940,941],{"__ignoreMap":393},[491,942,943,946],{"class":493,"line":494},[491,944,487],{"class":945},"sScJk",[491,947,949],{"class":948},"sZZnC"," extract_photos.py\n",[17,951,952],{},"This script will extract all files from the specified path within each zip archive and save them to your target directory, maintaining the directory structure.",[12,954,378],{"id":377},[17,956,957],{},"This updated Python script is a handy tool for automating the extraction of specific files from zip archives. Whether you're organizing photos from Google or managing backups, this script can save you time and effort. Happy coding!",[959,960,961],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":393,"searchDepth":394,"depth":394,"links":963},[964,965,966,967,968,969],{"id":437,"depth":397,"text":432},{"id":453,"depth":397,"text":454},{"id":477,"depth":397,"text":478},{"id":803,"depth":397,"text":804},{"id":881,"depth":397,"text":882},{"id":377,"depth":397,"text":378},"2024-06-23T15:44:03.462Z","In this blog post, I'll show you how to create a Python script that extracts files from zip archives to a specific path on your hard drive.  Google Takeout will allow users to extract all of their Google Photos to any number of large zip files.  After downloading, you are still required to extract to your own file system.  This script can help that by iterating over each zip and perform the extraction.","\u002Farticles\u002Fimages\u002Fpythonscript2.jpg",{},"\u002Farticles\u002Fgoogletakeout-extract-script",{"title":432,"description":971},"articles\u002Fgoogletakeout-extract-script",[978],"tools","X2MHVj0WJ__COABevlzA2jaK7l4Y6ysibzyoJIiF5iU",{"id":981,"title":982,"author":983,"body":984,"createdAt":1341,"description":1342,"extension":405,"img":1343,"meta":1344,"navigation":408,"path":1345,"seo":1346,"stem":1347,"tags":1348,"updatedAt":1341,"__hash__":1351},"articles\u002Farticles\u002F2023_BrowserAudioOptions.md","Comparing SpeechRecognition and MediaRecorder APIs in Web Browsers","[object Object]",{"type":9,"value":985,"toc":1335},[986,990,1000,1003,1007,1012,1018,1022,1033,1037,1040,1044,1047,1051,1057,1107,1111,1114,1118,1121,1126,1129,1140,1143,1146,1149,1152,1155,1161,1310,1313,1316,1318,1332],[12,987,989],{"id":988},"introduction","Introduction",[17,991,992,993,470,996,999],{},"When it comes to audio processing in web applications, two key APIs come to mind: ",[467,994,995],{},"SpeechRecognition",[467,997,998],{},"MediaRecorder",". While both deal with audio, they serve distinct purposes and are employed in different scenarios. In this post, we'll explore the differences between these two APIs and discuss their use cases, browser support, implementation details, and more.",[21,1001],{"style":23,"src":1002,"alt":25,"title":25},"\u002Farticles\u002Fimages\u002Fspeechrecognition_1.png",[12,1004,1006],{"id":1005},"speechrecognition-api","SpeechRecognition API",[1008,1009,1011],"h4",{"id":1010},"purpose","Purpose",[17,1013,1014,1015,1017],{},"The ",[467,1016,995],{}," API is designed for real-time speech-to-text conversion, making it ideal for applications that require instantaneous transcription of spoken language.",[1008,1019,1021],{"id":1020},"use-cases","Use Cases",[48,1023,1024,1027,1030],{},[51,1025,1026],{},"Voice-controlled applications",[51,1028,1029],{},"Transcription services",[51,1031,1032],{},"Voice commands in applications",[1008,1034,1036],{"id":1035},"browser-support","Browser Support",[17,1038,1039],{},"Supported in modern browsers, including Chrome and Firefox, though support might vary.",[1008,1041,1043],{"id":1042},"output","Output",[17,1045,1046],{},"Transcribed text based on recognized speech, with events and callbacks for handling recognition results.",[1008,1048,1050],{"id":1049},"implementation","Implementation",[17,1052,1053,1054,1056],{},"Setting up an instance of ",[467,1055,995],{},", attaching event listeners, and starting\u002Fstopping the recognition process.",[483,1058,1062],{"className":1059,"code":1060,"language":1061,"meta":393,"style":393},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F Example SpeechRecognition implementation\nconst recognition = new SpeechRecognition();\n\nrecognition.onresult = (event) => {\n  const transcript = event.results[0][0].transcript;\n  console.log('Transcription:', transcript);\n};\n\nrecognition.start();\n","javascript",[467,1063,1064,1069,1074,1078,1083,1088,1093,1098,1102],{"__ignoreMap":393},[491,1065,1066],{"class":493,"line":494},[491,1067,1068],{},"\u002F\u002F Example SpeechRecognition implementation\n",[491,1070,1071],{"class":493,"line":394},[491,1072,1073],{},"const recognition = new SpeechRecognition();\n",[491,1075,1076],{"class":493,"line":397},[491,1077,507],{"emptyLinePlaceholder":408},[491,1079,1080],{"class":493,"line":510},[491,1081,1082],{},"recognition.onresult = (event) => {\n",[491,1084,1085],{"class":493,"line":516},[491,1086,1087],{},"  const transcript = event.results[0][0].transcript;\n",[491,1089,1090],{"class":493,"line":522},[491,1091,1092],{},"  console.log('Transcription:', transcript);\n",[491,1094,1095],{"class":493,"line":528},[491,1096,1097],{},"};\n",[491,1099,1100],{"class":493,"line":534},[491,1101,507],{"emptyLinePlaceholder":408},[491,1103,1104],{"class":493,"line":540},[491,1105,1106],{},"recognition.start();\n",[1008,1108,1110],{"id":1109},"real-time-vs-offline-processing","Real-time vs. Offline Processing",[17,1112,1113],{},"Suited for real-time processing as it transcribes speech as it occurs.",[12,1115,1117],{"id":1116},"mediarecorder-api","MediaRecorder API",[1008,1119,1011],{"id":1120},"purpose-1",[17,1122,1014,1123,1125],{},[467,1124,998],{}," API is focused on recording audio and video streams, making it suitable for scenarios where capturing raw audio data for later use is required.",[1008,1127,1021],{"id":1128},"use-cases-1",[48,1130,1131,1134,1137],{},[51,1132,1133],{},"Audio recording applications",[51,1135,1136],{},"Voicemail services",[51,1138,1139],{},"Any scenario requiring capture and storage of audio data",[1008,1141,1036],{"id":1142},"browser-support-1",[17,1144,1145],{},"Widely supported in modern browsers, including Chrome, Firefox, Safari, and Edge.",[1008,1147,1043],{"id":1148},"output-1",[17,1150,1151],{},"Audio (and video) data saved as a media file, often in compressed formats like WebM or MP3.",[1008,1153,1050],{"id":1154},"implementation-1",[17,1156,1157,1158,1160],{},"Setting up a ",[467,1159,998],{}," instance, defining the media type and format, specifying the source, and handling recording events.",[483,1162,1164],{"className":1059,"code":1163,"language":1061,"meta":393,"style":393},"\u002F\u002F Example MediaRecorder implementation\nconst getUserMedia = navigator.mediaDevices.getUserMedia;\n\ngetUserMedia({ audio: true })\n.then((stream) => {\nconst mediaRecorder = new MediaRecorder(stream);\nconst chunks = [];\n\n    mediaRecorder.ondataavailable = (event) => {\n      if (event.data.size > 0) {\n        chunks.push(event.data);\n      }\n    };\n\n    mediaRecorder.onstop = () => {\n      const audioBlob = new Blob(chunks, { type: 'audio\u002Fwav' });\n      const audioUrl = URL.createObjectURL(audioBlob);\n      console.log('Audio URL:', audioUrl);\n    };\n\n    mediaRecorder.start();\n\n    \u002F\u002F Stop recording after 5000 milliseconds (5 seconds)\n    setTimeout(() => {\n      mediaRecorder.stop();\n    }, 5000);\n})\n.catch((error) => {\nconsole.error('Error accessing microphone:', error);\n});\n",[467,1165,1166,1171,1176,1180,1185,1190,1195,1200,1204,1209,1214,1219,1224,1229,1233,1238,1243,1248,1253,1257,1261,1266,1270,1275,1280,1285,1290,1295,1300,1305],{"__ignoreMap":393},[491,1167,1168],{"class":493,"line":494},[491,1169,1170],{},"\u002F\u002F Example MediaRecorder implementation\n",[491,1172,1173],{"class":493,"line":394},[491,1174,1175],{},"const getUserMedia = navigator.mediaDevices.getUserMedia;\n",[491,1177,1178],{"class":493,"line":397},[491,1179,507],{"emptyLinePlaceholder":408},[491,1181,1182],{"class":493,"line":510},[491,1183,1184],{},"getUserMedia({ audio: true })\n",[491,1186,1187],{"class":493,"line":516},[491,1188,1189],{},".then((stream) => {\n",[491,1191,1192],{"class":493,"line":522},[491,1193,1194],{},"const mediaRecorder = new MediaRecorder(stream);\n",[491,1196,1197],{"class":493,"line":528},[491,1198,1199],{},"const chunks = [];\n",[491,1201,1202],{"class":493,"line":534},[491,1203,507],{"emptyLinePlaceholder":408},[491,1205,1206],{"class":493,"line":540},[491,1207,1208],{},"    mediaRecorder.ondataavailable = (event) => {\n",[491,1210,1211],{"class":493,"line":546},[491,1212,1213],{},"      if (event.data.size > 0) {\n",[491,1215,1216],{"class":493,"line":552},[491,1217,1218],{},"        chunks.push(event.data);\n",[491,1220,1221],{"class":493,"line":558},[491,1222,1223],{},"      }\n",[491,1225,1226],{"class":493,"line":564},[491,1227,1228],{},"    };\n",[491,1230,1231],{"class":493,"line":570},[491,1232,507],{"emptyLinePlaceholder":408},[491,1234,1235],{"class":493,"line":576},[491,1236,1237],{},"    mediaRecorder.onstop = () => {\n",[491,1239,1240],{"class":493,"line":582},[491,1241,1242],{},"      const audioBlob = new Blob(chunks, { type: 'audio\u002Fwav' });\n",[491,1244,1245],{"class":493,"line":588},[491,1246,1247],{},"      const audioUrl = URL.createObjectURL(audioBlob);\n",[491,1249,1250],{"class":493,"line":594},[491,1251,1252],{},"      console.log('Audio URL:', audioUrl);\n",[491,1254,1255],{"class":493,"line":600},[491,1256,1228],{},[491,1258,1259],{"class":493,"line":606},[491,1260,507],{"emptyLinePlaceholder":408},[491,1262,1263],{"class":493,"line":612},[491,1264,1265],{},"    mediaRecorder.start();\n",[491,1267,1268],{"class":493,"line":618},[491,1269,507],{"emptyLinePlaceholder":408},[491,1271,1272],{"class":493,"line":624},[491,1273,1274],{},"    \u002F\u002F Stop recording after 5000 milliseconds (5 seconds)\n",[491,1276,1277],{"class":493,"line":629},[491,1278,1279],{},"    setTimeout(() => {\n",[491,1281,1282],{"class":493,"line":635},[491,1283,1284],{},"      mediaRecorder.stop();\n",[491,1286,1287],{"class":493,"line":641},[491,1288,1289],{},"    }, 5000);\n",[491,1291,1292],{"class":493,"line":647},[491,1293,1294],{},"})\n",[491,1296,1297],{"class":493,"line":653},[491,1298,1299],{},".catch((error) => {\n",[491,1301,1302],{"class":493,"line":659},[491,1303,1304],{},"console.error('Error accessing microphone:', error);\n",[491,1306,1307],{"class":493,"line":665},[491,1308,1309],{},"});\n",[1008,1311,1110],{"id":1312},"real-time-vs-offline-processing-1",[17,1314,1315],{},"Can be used for both real-time recording and offline processing, as recorded data can be saved and processed later.",[12,1317,378],{"id":377},[17,1319,1320,1321,470,1323,1325,1326,1328,1329,1331],{},"In conclusion, the choice between ",[467,1322,995],{},[467,1324,998],{}," depends on the specific requirements of your application. If real-time speech-to-text conversion is crucial, the ",[467,1327,995],{}," API is the go-to option. On the other hand, if you need to capture and store audio for playback or further processing, the ",[467,1330,998],{}," API is more suitable. Ensure to consider browser support and potential fallbacks based on your application's needs.",[959,1333,1334],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":393,"searchDepth":394,"depth":394,"links":1336},[1337,1338,1339,1340],{"id":988,"depth":397,"text":989},{"id":1005,"depth":397,"text":1006},{"id":1116,"depth":397,"text":1117},{"id":377,"depth":397,"text":378},"2023-12-02","Explore the distinctions between the SpeechRecognition and MediaRecorder APIs in web browsers with our latest blog post. Discover their unique purposes, use cases, and implementation details. Whether you're interested in real-time speech-to-text conversion or capturing and storing audio data, this comparison will guide you in choosing the right API for your web application. Dive into the world of audio processing and make informed decisions based on browser support, output formats, and more.","\u002Farticles\u002Fimages\u002Fspeechrecognition_2.png",{},"\u002Farticles\u002F2023_browseraudiooptions",{"title":982,"description":1342},"articles\u002F2023_BrowserAudioOptions",[1349,1350],"chrome","web","gpob4_4BcdcvaPduD0f1E6PeB04iS3OJ2TTnmFKFxB0",1781574757961]