MovieLife 电影生活

news2024/11/16 6:00:36

MovieLife 电影生活

今天看到一个很有意思的项目:https://www.lampysecurity.com/post/the-infinite-audio-book

在这里插入图片描述

“我有一个看似愚蠢的想法。通常,这类想法只是一闪而过,很少会付诸实践。但这次有所不同。假如你的生活是一部电影,它会讲述什么故事?会发生什么?我的想法就是从这里开始的。随着 AI 的兴起,我想看看是否可以让 AI 实时讲述我的生活。我们的设想是让相机拍摄一张照片,生成对照片的描述,然后由 ChatGPT 基于所看到的内容写一个叙事场景,再将文本转换为语音并播放。”

我的实现

在整个项目中,我使用了笔记本的摄像头进行操作,运行在笔记本上,感觉非常有趣。ChatGPT的描述充满了正能量!最初的代码无法运行,因此我参考了https://platform.openai.com/docs/guides/vision,进行了修改,并成功在我的电脑上运行起来。至于树莓派,我了解得不多,正在考虑是否可以在手机上部署,但还没有深入研究。

项目概念

  • 创意起源:作者反思了人生如电影的概念,探索了使用AI实时叙述他的人生。
  • 技术整合:该项目利用了OpenAI的各种服务,包括图像识别、语言模型和文字转语音。

硬件设置

  • 选择设备:一个带有Pi相机和Pi Sugar 3电池的Raspberry Pi Zero,以便携带。
  • 其他要求:
    • 带有micro HDMI的显示器,用于配置。
    • 鼠标/键盘进行交互。
    • USB micro转female A适配器。
    • SD卡用于Raspberry Pi OS。
    • 由于缺乏音频插孔,需要无线耳机。

设计和3D打印

  • 外壳设计:作者修改了现有的3D外壳设计,以适应电池,并使用Bambu Lab P1S 3D Printer。

软件和API集成

  • OpenAI API设置:
    • 创建账户并生成API密钥。
    • 解释API调用成本和使用情况。

代码实现

  • 编程语言:选择Python来编码项目。

  • 分步细节:

    • 配置文件.env

      OPENAI_API_KEY="这里填入你的API_KEY"
      
    • 导入必要的库。

      from pathlib import Path
      from openai import OpenAI
      import requests
      import os
      import cv2
      import base64
      import time
      import pygame
      from dotenv import load_dotenv
      
      
      # 加载 .env 文件
      load_dotenv()
      # OpenAI API key
      client = OpenAI()
      
      # OpenAI API Key
      api_key = os.getenv("OPENAI_API_KEY")
      # Path to your image
      image_path = "vision.jpg"
      
      # Getting the base64 string
      base64_image = "error"
      
      headers = {
          "Content-Type": "application/json",
          "Authorization": f"Bearer {api_key}"
      }
      
      payload = {
        "model": "gpt-4o-mini",
        "messages": [
          {
            "role": "user",
            "content": [
              {
                "type": "text",
                "text": "请描述这张图片?"
              },
              {
                "type": "image_url",
                "image_url": {
                  "url": f"data:image/jpeg;base64,{base64_image}"
                }
              }
            ]
          }
        ],
        "max_tokens": 300
      }
      
      
    • 从相机捕获图像。

      def capture_webcam_photo(save_directory="webcam_photos"):
          # Create directory if it doesn't exist
          if not os.path.exists(save_directory):
              os.makedirs(save_directory)
      
          # Open default camera (usually the first camera)
          cap = cv2.VideoCapture(1)
      
          # Capture frame-by-frame
          ret, frame = cap.read()
      
          # Generate a unique filename
          filename = os.path.join(save_directory, "webcam_photo.jpg")
      
          # Save the captured frame as an image
          cv2.imwrite(filename, frame)
      
          # Release the capture
          cap.release()
      
          return filename
      
    • 将图像编码为base64格式,以便提交API。

      # Function to encode the image
      def encode_image(image_path):
        with open(image_path, "rb") as image_file:
          return base64.b64encode(image_file.read()).decode('utf-8')
      
    • 使用OpenAI的模型根据图像描述生成叙述性响应。

      def generate_response(prompt):
          name = "BoBo"
          age = "60"
          location = "体操之乡 湖北仙桃"
          response = client.chat.completions.create(
              model="gpt-4o-mini",
              messages=[
                  {"role": "system",
                   "content": "你是一部电影的叙述者,讲述一个名叫 " + name + "。他的年龄  " + age + " ,生活在 " + location + "。当你看到一张场景图片时,你可以从" + name + "的角度描述这张照片,所有人物都用第三人称。 "},
                  {"role": "user", "content": prompt}
              ]
          )
          return response.choices[0].message.content
      
    • 将文本响应转换为语音并播放。

      def text_to_speech(text):
          speech_file_path = Path(__file__).parent / "speech.mp3"
          response = client.audio.speech.create(
            model="tts-1",
            voice="alloy",
            input=text
          )
      
          response.stream_to_file(speech_file_path)
          return speech_file_path
      
      def play_mp3(file_path):
          # Initialize Pygame
          pygame.init()
      
          try:
              # Initialize the mixer
              pygame.mixer.init()
      
              # Load the MP3 file
              pygame.mixer.music.load(file_path)
      
              # Play the MP3 file
              pygame.mixer.music.play()
      
              # Wait until the music finishes playing
              while pygame.mixer.music.get_busy():
                  pygame.time.Clock().tick(10)  # Adjust the playback speed
          except pygame.error as e:
              print(f"Error playing MP3: {e}")
          finally:
              # Cleanup Pygame
              pygame.mixer.music.stop()
              pygame.mixer.quit()
              pygame.quit()
      

      主函数:

      while True:
          start_time = time.time()
      
          saved_path = capture_webcam_photo()
          base64_image = encode_image(saved_path)
      
          # 将图像插入到 payload 中
          payload["messages"][0]["content"][1]["image_url"]["url"] = "data:image/jpeg;base64," + base64_image
      
          # 发送请求
          response = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)
      
          # 检查响应状态
          if response.status_code != 200:
              print(f"Error: {response.status_code} - {response.text}")
              continue  # 跳过此次循环,继续尝试
      
          jsonZ = response.json()
      
          # 检查是否有 'choices' 键
          if 'choices' in jsonZ and len(jsonZ['choices']) > 0:
              try:
                  response_text = generate_response(jsonZ["choices"][0]["message"]["content"])
                  output_file = text_to_speech(response_text)  # 
                  play_mp3(output_file)  # 
              except KeyError as e:
                  print(f"KeyError: {e}")
                  print("Received response:", jsonZ)
                  continue  # 跳过此循环并记录错误
          else:
              print("No choices found in response")
      
          # 计算经过的时间
          elapsed_time = time.time() - start_time
      
          # 等待剩余时间
          remaining_time = max(0, 20 - int(elapsed_time))
          time.sleep(remaining_time)
      

主要功能

  • 连续运行:主循环每20秒捕获一次图像,通过OpenAI API进行处理,生成叙述,转换为语音,并播放。

完整代码

'''
@File    : movielife
@Author  : Bobo
@Blog    : https://blog.csdn.net/chinagaobo
@Note    : This code is for learning and communication purposes only
'''

from pathlib import Path
from openai import OpenAI
import requests
import os
import cv2
import base64
import time
import pygame
from dotenv import load_dotenv


# 加载 .env 文件
load_dotenv()
# OpenAI API key
client = OpenAI()

# OpenAI API Key
api_key = os.getenv("OPENAI_API_KEY")
# Path to your image
image_path = "vision.jpg"

# Getting the base64 string
base64_image = "error"

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {api_key}"
}

payload = {
  "model": "gpt-4o-mini",
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "请描述这张图片?"
        },
        {
          "type": "image_url",
          "image_url": {
            "url": f"data:image/jpeg;base64,{base64_image}"
          }
        }
      ]
    }
  ],
  "max_tokens": 300
}


# Function to encode the image
def encode_image(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')


def generate_response(prompt):
    name = "BoBo"
    age = "60"
    location = "体操之乡 湖北仙桃"
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system",
             "content": "你是一部电影的叙述者,讲述一个名叫 " + name + "。他的年龄  " + age + " ,生活在 " + location + "。当你看到一张场景图片时,你可以从" + name + "的角度描述这张照片,所有人物都用第三人称。 "},
            {"role": "user", "content": prompt}
        ]
    )
    return response.choices[0].message.content


def text_to_speech(text):
    speech_file_path = Path(__file__).parent / "speech.mp3"
    response = client.audio.speech.create(
        model="tts-1",
        voice="alloy",
        input=text
    )

    response.stream_to_file(speech_file_path)
    return speech_file_path


def capture_webcam_photo(save_directory="webcam_photos"):
    # Create directory if it doesn't exist
    if not os.path.exists(save_directory):
        os.makedirs(save_directory)

    # Open default camera (usually the first camera)
    cap = cv2.VideoCapture(0)  # 使用内置摄像头

    # Capture frame-by-frame
    ret, frame = cap.read()

    # Generate a unique filename
    filename = os.path.join(save_directory, "webcam_photo.jpg")

    # Save the captured frame as an image
    cv2.imwrite(filename, frame)

    # Release the capture
    cap.release()

    return filename


def play_mp3(file_path):
    # Initialize Pygame
    pygame.init()

    try:
        # Initialize the mixer
        pygame.mixer.init()

        # Load the MP3 file
        pygame.mixer.music.load(file_path)

        # Play the MP3 file
        pygame.mixer.music.play()

        # Wait until the music finishes playing
        while pygame.mixer.music.get_busy():
            pygame.time.Clock().tick(10)  # Adjust the playback speed
    except pygame.error as e:
        print(f"Error playing MP3: {e}")
    finally:
        # Cleanup Pygame
        pygame.mixer.music.stop()
        pygame.mixer.quit()
        pygame.quit()


while True:
    start_time = time.time()

    saved_path = capture_webcam_photo()
    base64_image = encode_image(saved_path)

    # 将图像插入到 payload 中
    payload["messages"][0]["content"][1]["image_url"]["url"] = "data:image/jpeg;base64," + base64_image

    # 发送请求
    response = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)

    # 检查响应状态
    if response.status_code != 200:
        print(f"Error: {response.status_code} - {response.text}")
        continue  # 跳过此次循环,继续尝试

    jsonZ = response.json()

    # 检查是否有 'choices' 键
    if 'choices' in jsonZ and len(jsonZ['choices']) > 0:
        try:
            response_text = generate_response(jsonZ["choices"][0]["message"]["content"])
            output_file = text_to_speech(response_text)  # 
            play_mp3(output_file)  # 
        except KeyError as e:
            print(f"KeyError: {e}")
            print("Received response:", jsonZ)
            continue  # 跳过此循环并记录错误
    else:
        print("No choices found in response")

    # 计算经过的时间
    elapsed_time = time.time() - start_time

    # 等待剩余时间
    remaining_time = max(0, 20 - int(elapsed_time))
    time.sleep(remaining_time)

实测案例

chatGPT的描述:在这张图片中 Bobo看到一个男子坐在桌前 面带微笑 眼镜反射出柔和的光泽 这个男人的手肘支撑在下巴旁 看起来十分放松 似乎正沉浸在与人交流的愉悦中 Bobo想这样的瞬间很难得 尤其是在压力重重的生活中 室内环境给人一种温馨舒适的感觉 整齐的墙面与那扇门形成一种和谐的背景 似乎在提醒每一个人 生活中依旧有着宁静与安详 Bobo的心情也随之变得轻松起来 彷佛可以感受到这个男子所散发出的友好气息 他觉得在这个快速发展的时代 能有这样一份从容不迫和愉快的交流 是多么美好的事情 或许这就是生活的意义所在。

测试案例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2160113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cisco Secure Firewall Threat Defense Virtual 7.6.0 发布下载,新增功能概览

Cisco Secure Firewall Threat Defense Virtual 7.6.0 - 思科下一代防火墙虚拟设备 (FTDv) Firepower Threat Defense (FTD) Software for ESXi & KVM 请访问原文链接:https://sysin.org/blog/cisco-firepower-7/,查看最新版。原创作品&#xff0c…

为什么三星、OPPO、红米都在用它?联发科12nm级射频芯片的深度剖析

小道消息 联发科和联电在12纳米制程技术方面有潜在的合作机会… 2024年初根据相关报道,联电和英特尔宣布12纳米制程工艺合作。此外,市场传闻称联发科可能会考虑将部分订单转投给英特尔,但也有机会成为联电12纳米制程的客户。 联发科在射频产品线涵盖多种工艺和应用领域。在…

软件测试面试八股文(含文档)

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 一般软件测试的面试分为三轮:笔试,HR面试,技术面试。 前两轮,根据不同企业,或有或无,但最…

建立分支提交代码

git分支 git branch 产看当前分支 git branch -a 查看所有分支 git checkout 分支名 切换分支 git checkout -b 分支名 建立分支(仅仅是在本地建立了,并没有关联线上) git push --set-upstream origin 分支名 把本地分支推到先线上 建立分支…

3、SRGAN

3、SRGAN SRGAN论文链接:SRGAN SRGAN(超分辨率生成对抗网络)是在2017年由Christian Ledig等人在论文《Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network》中提出的。该模型引入了基于GAN(…

9.5HSV体系进行颜色分割

基本概念 inRange() 函数是 OpenCV 中用于图像处理的一个非常有用的函数,即从图像中提取出介于指定范围内的像素值。这个函数在图像处理中特别有用,比如颜色检测、背景去除等应用。它主要用于图像的阈值处理,但与其他阈值方法(如…

AOT源码解析4.1-model主体解析

1 输入数据 VOS的数据集处理操作可见数据集操作,这里是进行数据集提取完毕后的操作。 图2:如图所示,使用datasets提取出数据之后,在模型训练阶段对数据做图中操作。即:将batch_size大小的ref_imgs、prev_imgs&#x…

【JavaEE】——线程“饿死问题” wait notify

阿华代码,不是逆风,就是我疯,你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你! 目录 引子: 一:情景引入 二:线程饿死问题 1:线程饿死 2&a…

24 C 语言常用的字符串处理函数详解:strlen、strcat、strcpy、strcmp、strchr、strrchr、strstr、strtok

目录 1 strlen 1.1 函数原型 1.2 功能说明 1.3 案例演示 1.4 注意事项 2 strcat 2.1 函数原型 2.2 功能说明 2.3 案例演示 2.4 注意事项 3 strcpy 3.1 函数原型 3.2 功能说明 3.3 案例演示 3.4 注意事项 4 strcmp 4.1 函数原型 4.2 功能说明 4.3 案例演示 …

在 VS Code 中调试 C++ 项目

选择调试器环境 从预定义的调试配置中进行选择,生成预定义launch.json文件,可能是空模板 {// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft…

Qwen2-VL全面解读!阿里开源多模态视觉语言模型,多项超越GPT4o与Claude 3.5-Sonnet

文章链接:https://arxiv.org/pdf/2409.12191 Github链接:https://github.com/QwenLM/Qwen2-VL 亮点直击 本文介绍了Qwen系列大型视觉语言模型的最新成员:Qwen2-VL系列,该系列包括三款开放权重模型,总参数量分别为20亿、…

QString 构建SQL语句可以往数据库中添加“\n“字符串

网上找了很多案例关于怎么样能在Mysql数据库中插入带\n的字符串,如图: 本以为很容易的一件事,没想到思考了半天,在这里记录一下,以为\n是转义字符的原因,所以并不是我想的那么简单。网上有用R(“…

力扣 困难 154.寻找旋转排序数组中的最小值 II

文章目录 题目介绍题解 题目介绍 题解 题源: 153.寻找旋转排序数组中的最小值 在此基础上,进行二分之前,单独处理一下左指针和最后一个数相同的情况就好了。 class Solution {public int findMin(int[] nums) {int left 0, right nums.le…

使用豆包Marscode 创建了一个”天气预报“小应用

以下是「豆包MarsCode 体验官」优秀文章,作者一拳干爆显示器。 前言 本文介绍了我第一次使用我在MarsCode IDE制作了一款天气预报的应用 其中在正文的头部以及结语部分发表了我在MarsCode编程中的体验情况,而正文的中间主要是我项目制作的细节步骤 豆…

【自动驾驶】基于车辆几何模型的横向控制算法 | Pure Pursuit 纯跟踪算法详解与编程实现

写在前面: 🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝 个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。 🔍 本文系 清流君 原创之作&…

Face++API调用

人脸检测API调用 import requests import json #将自己的KEY和Secret进行替换 API_KEYyour_API_KET API_SECRETyour_API_Secret# 人脸识别的URL URL https://api-cn.faceplusplus.com/facepp/v3/detect# 请求参数,需要什么参数传入什么参数 data {"api_key":API…

力扣2208.将数组各元素总和减半需要最少次数(贪心+堆)

题目描述 给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。(注意,在后续操作中你可以对减半过的数继续执行操作)请你返回将 nums 数组和 至少 减少一半的 最少 操作数。 示例…

零基础入门AI大模型应用开发——第三天:使用python实现问答机器人

一、简介 问答机器人是一种能够理解用户提问并提供相关答案的程序。它可以用于各种场景,如客户支持、在线教育、信息检索等。用户通过自然语言输入问题,机器人则通过分析问题并检索相关信息来提供回答。 使用什么技术实现的? 自然语言处理&…

Leetcode 合并区间

我们借助一个辅助链表(元素类型是一维数组)来进行结果统计。 这个算法解决了“合并区间”的问题,具体要求是给定一组区间(每个区间有开始和结束位置),如果两个区间有重叠,那么需要将它们合并成一个区间,并…

【Linux】ubuntu 16.04 搭建jdk 11 环境(亲测可用)

目录 0.环境 1.题外话 2.详细 0.环境 windows11 主机 Virtual Box 7.0 ubuntu 16.04系统 想搭建个 jdk11的环境,用于项目 1.题外话 因为虚拟机与主机传输文件不方便,所以可以尝试用共享文件夹的方式传输,亲测可用,参考以下博…