做了一个随机视频的网页

去年,我在GPT 4 的帮助下,做了个“每日一问“的网页。当时本想使用framer来做的,但发现后台数据库不方便,便采用了supabase做问题数据库,然后让chatGPT写的网页代码,代码托管到了阿里云服务器。

不过,虽然当时完成了自己的第一个编程作品,但效果并不好,数据不够,并不能实现问题随机以此出现。而且,网页加载非常慢。

时间到了今年,博客网站需要付费,我考虑找个便宜的平台自建。最后考虑用网络上的astro模版,然后自己修改相应的页面设置。

但修改设置对于来我说也是有一些难度的,而且我一直有个问题没有解决,就是如何将之前博客的json文件导入到新博客项目里。

1

这个问题,困扰了我很长一段时间。

因为astro是可以通过github部署到vercel上的,所以,我刚开始以为只需要把json文件上传到github就可以了。但这显然是错误的。

之前我将这个困惑提交给chatgpt,它说要转化格式,然后给我一段代码,让我放到github项目里。我按照逻辑去做了,然后我发现python文件并没有转化。因为部署到vercel上,并不会主动执行python,除非你增加触发条件。当然,作为编程小白,当时并不知道这些。

然后,在claude3.5出现后,我将同样的问题提交给了它。我发现它更擅长理解问题,或者说,能引导用户提出正确的问题,因为它会在每次回答后,补充可能存在其他的问题,或者其他资料。

在摸索一段时间后,我意识到首先需要将json文件转成符合项目要求的markdown格式,然后将markdown格式的文字放在合适的地方,这样部署的项目才能将这些文章呈现出来。

当然,这两步我是前后才意识到了,花了3-4天的摸索。

2

解决了导入之前博客文章的问题之后,就是网站设置了,包括导航页面,网站域名之类的,这些并不算复杂,配置也相对简单。并没有花费我很多时间。

重点是我既然利用了astro自建了博客,那么我是否可以按照自己的想法来建立自己的网页,比如带用时间轴的动态,比如将之前的项目都弄过来。

这时,我刚好看到了一个随机视频的项目,我好奇检查了网页代码,然后我发现它是将视频链接放在

一个开源的google slide项目里,然后网页代码加载了视频链接,然后实现了随机视频的项目。

然后,我就觉得我可以通过supabase或者其他数据库完成类似的项目,部署到自己的网页上?

这样的想法,激励着我。然后我将这样的想法提交给了claude。

3

我直接把该网页的代码复制给claude,让其在我的博客上实现相关页面,这个对于claude来说很简单。

但在做的过程中,我考虑使用notion作为数据库,也就是我在notion上建立一个数据表格,然后通过notion api将其同步到我的博客上。这个比我之前用supabase更为了省事,但我需要重新了解下大概逻辑。

但这个对于claude而言,并不是很困难。claude让我新建一个notionApi.js 与getvideo.js

import { Client } from '@notionhq/client';

console.log('NOTION_API_KEY:', import.meta.env.NOTION_API_KEY ? 'Set' : 'Not set');
console.log('NOTION_DATABASE_ID:', import.meta.env.NOTION_DATABASE_ID);

const notion = new Client({ auth: import.meta.env.NOTION_API_KEY });
const databaseId = import.meta.env.NOTION_DATABASE_ID;

export async function getVideos() {
  try {
    console.log('Fetching videos from Notion...');
    console.log('Using database ID:', databaseId);
    
    if (!databaseId) {
      throw new Error('NOTION_DATABASE_ID is not set');
    }

    const response = await notion.databases.query({
      database_id: databaseId,
    });
    console.log('Notion response:', JSON.stringify(response, null, 2));

    if (!response.results || response.results.length === 0) {
      console.log('No results found in the Notion response');
      return [];
    }

    const videos = response.results.map(page => {
      console.log('Processing page:', JSON.stringify(page, null, 2));
      return {
        id: page.id,
        title: page.properties.Title?.title[0]?.plain_text || 'Untitled',
        link: page.properties.Link?.url || '',
        author: page.properties.Author?.rich_text[0]?.plain_text || 'Unknown',
        nugget: page.properties.Nugget?.rich_text[0]?.plain_text || '',
        tags: page.properties.Tags?.multi_select?.map(tag => tag.name) || []
      };
    });

    console.log('Processed videos:', videos);
    return videos;
  } catch (error) {
    console.error('Error fetching videos from Notion:', error);
    return [];
  }
}
import { getVideos } from '../../utils/notionApi';

export async function get() {
  try {
    const videos = await getVideos();
    return new Response(JSON.stringify(videos), {
      status: 200,
      headers: {
        'Content-Type': 'application/json'
      }
    });
  } catch (error) {
    return new Response(JSON.stringify({ error: 'Failed to fetch videos' }), {
      status: 500,
      headers: {
        'Content-Type': 'application/json'
      }
    });
  }
}

这个过程中,我学习了noiton api相关知识,然后js代码全靠claude,其中因为claude并不能看notion数据库,所以在抓取数据库内容的时候,出现了一些问题。claude的逻辑,是通过错误提示来确定错误的原因,然后进行修改。

这让我初步完成了项目。

4

但我发现完善项目的欲望是强大的。

因为参考里的视频链接都是youtube的,然后使用的都是嵌入式的链接,但我自己直接把youtube链接添加到数据库,却发现并不能在网页上呈现出来。所以,我需要让数据库里的链接,都能被代码处理。不仅是youtube,还有bilibili等。

这个过程并不算复杂,只是bilibili的iframe格式并不好用,直接用iframe并不能被检测出来。所以,代码需要检测bilibili链接,然后做单独处理。

function getEmbedCode(link) {
            // 检测 Bilibili 链接
            const bilibiliRegex = /https?:\/\/(www\.)?bilibili\.com\/video\/(BV[\w]+)/;
            const bilibiliMatch = link.match(bilibiliRegex);
            
            if (bilibiliMatch) {
                const videoId = bilibiliMatch[2];
                return `<iframe src="//player.bilibili.com/player.html?bvid=${videoId}&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>`;
            }
            
            // YouTube 嵌入代码
            if (link.includes('youtube.com') || link.includes('youtu.be')) {
                return `<iframe src="${link}" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>`;
            }
            
            // Vimeo 嵌入代码
            if (link.includes('vimeo.com')) {
                return `<iframe src="${link}" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>`;
            }
            
            // 对于其他未知的链接,我们可以尝试直接嵌入,或者显示一个链接
            return `<a href="${link}" target="_blank" rel="noopener noreferrer">Watch Video</a>`;
        }

另外一个问题是,视频播放器尺寸的问题。最好的效果是视频播放器尺寸是固定的。然后所有视频都是以这个尺寸播放。但刚开始的效果是,在未点击播放按钮的时候,视频播放器尺寸特别小,只有点击播放后,才会调整成更大尺寸。

为了解决这个问题,我跟claude 好几次对话,才真正解决这个问题

function adjustVideoSize() {
            const streamContainer = document.getElementById('streamContainer');
            const iframe = document.getElementById('stream').querySelector('iframe');
            
            if (iframe) {
                const containerWidth = streamContainer.clientWidth;
                const targetHeight = containerWidth * (9 / 16);

                iframe.style.width = `${containerWidth}px`;
                iframe.style.height = `${targetHeight}px`;
            }
        }

<style>
    #stream iframe {
        width: 100%;
        height: 100%;
        aspect-ratio: 16 / 9;
    }
</style>

但在这个过程中,又发现了另一个问题。

编程就是发现问题,解决问题呀。

bilibili链接一旦播放,会直接跳转到bilibili的网站,这显然并不是我想要的。所以,我在解决播放尺寸和对齐问题后,又开始处理bilibili链接播放问题。

这又让我花费了不少时间,感觉做一个项目,总有新问题。

5

这些问题解决后,我想调整页面内容宽度,但发现改完之后,很多需要调整,我就放弃了。

然后,

我想,我在telegram频道里有个值得一看的视频,其实都可以同步到notion里,然后在网站上呈现。这个想法,让我可以了解之前一直感兴趣的tg bot项目,我需要通过tg bot来抓取telegram更新的内容,然后通过noiton api来同步到notion数据库。

这个过程中,我花了一些时间了解频道CHAT_ID,然后让telegram里的信息能够按要求同步到noiton数据库里。

这一步虽然对我比较陌生,但claude执行起来,却没有什么问题。只要我想好抓取所有内容还是之后更新的内容,抓取的数据处理与notion相符合就行。

稍微比较麻烦的是,视频链接里标题的获取,youtube最后采用了YoutubeDL这个项目,而bilibili在几次尝试后,我选择了放弃,还是手动填写吧。

def get_video_title(url):
    ydl_opts = {
        'quiet': True,
        'no_warnings': True,
    }
    with YoutubeDL(ydl_opts) as ydl:
        try:
            info = ydl.extract_info(url, download=False)
            return info.get('title', '未知标题')
        except DownloadError as e:
            logging.error(f"无法获取视频标题: {url}, 错误: {e}")
            return '未知标题'

6

解决了上面的问题之后,这个项目基本是完成了。但还有一个问题。将tg频道的内容同步到notion如何自动执行。

最后,想到了github action完成。

name: Sync Telegram to Notion

on:
  schedule:
    - cron: '0 0 * * *'  # 每天运行一次
  workflow_dispatch:  # 允许手动触发

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: '3.x'
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run sync script
      env:
        TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
        CHAT_ID: ${{ secrets.CHAT_ID }}
        NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
        DATABASE_ID: ${{ secrets.DATABASE_ID }}
      run: python channel2n.py

这样其每天便会自动同步到notion。

7

至此,我便完成了将telegram频道内容同步到notion数据库,然后将notion数据库里的内容同步到自己博客。

下面是项目页面

项目页面

个人感觉还不错,然后在做这个过程中,我对编程也有了更多理解,虽然很多代码是靠claude写的,但断断续续也理解了一些逻辑,勉强能看懂代码了。然后我也理解和学会如何使用github托管本地代码了。

8

这个项目把我带入到了编程的世界,后面我也将会分享一些其他依靠AI实现的项目。

欢迎订阅我的博客

偶尔更新,保持联系.