将 ffmpeg 上传到 Azure 函数环境路径 [Python]

Upload ffmpeg to Azure Function Environment PATH [Python]

我正在做音频提取项目。我的 python 脚本中使用了 Audioread 库。 Audioread 要求 FFMPEG 存在于 linux /usr/bin 中。如果FFMPEG存在于/usr/bin,代码 audioread.audio_open(XXX.m4a)可以运行不报错,如果不存在,则输出 NoBackendError

我可以在我的本地 linux 系统中成功地 运行 我的代码。但是,代码会在 Azure Function 中输出 NoBackendError。我的猜测是 ffmpeg 没有部署到 /usr/bin,而是部署在 /home/site/wwwroot。我的 python 代码在 PATH 中找不到 ffmpeg。

我曾尝试在我的 python 脚本中使用 os.popen('mv /home/site/wwwroot/ffmpeg /usr/bin/ffmpeg') 将 ffmpeg 移动到 PATH,但它不起作用。我想原因应该是我没有添加sudo,但是我不知道Azure Function Linux平台的密码。

请帮帮我!

I think the reason should be I did not add sudo, but I dont know the password of Azure Function Linux platform.

用户可以使用 sudo 命令在 Linux 虚拟机上使用提升的权限 运行 命令。但是,体验可能会因系统的配置方式而异。

1.SSH 密钥和密码或仅密码 - 虚拟机配置了证书(.CER 文件)作为以及密码,或只是用户名和密码。在这种情况下,sudo 将在执行命令之前提示输入 用户密码

2.仅 SSH 密钥 - 为虚拟机提供了证书(.cer 或 .pem 文件),但没有密码。在这种情况下 sudo 在执行命令之前不会提示输入用户密码

您可以参考以下link:http://azure.microsoft.com/en-us/documentation/articles/virtual-machines-linux-use-root-privileges/


我按照官方教程 Create your first Python function in Azure 为 Python 创建了一个 HttpTrigger 函数,并尝试了不同的方法使 ffmpeg 在 Azure Functions 中工作,它适用于我.

这些是我的步骤:

  1. 在我的本地 Windows 机器上安装 Azure Functions Core Tools 以创建名为 MyFunctionProj 和一个名为 HttpTrigger.

    的函数
  2. 在上传 ffmpeg 部署之前,通过使用以下代码更改官方示例代码,检查了我的 Azure Functions 实例的 OS 平台架构。

    # add these codes
    import platform, os
    .....
    
    def main(req: func.HttpRequest) -> func.HttpResponse:
        if name:
            return func.HttpResponse(f"Hello {name}! {platform.architecture()}")
    
    

    其结果在浏览器中为Hello krishna! ('64bit', '')

  3. 然后我将从 https://johnvansickle.com/ffmpeg/ 下载的 ffmpeg AMD64 静态二进制文件放入我的 MyFunctionProj 并更改下面的代码以检查文件路径,并命令 func azure functionapp publish MyFunctionProj 发布到 Azure。

    def main(req: func.HttpRequest) -> func.HttpResponse:
        if name:
            return func.HttpResponse(f"Hello {name}! {platform.architecture()} {os.listdir()} {os.listdir('HttpTrigger')}")
    
    

输出:

Hello krishna! ('64bit', '') ['in.mp4', 'ffmpeg', 'host.json', 'requirements.txt', 'ffmpeg.exe', '.python_packages', 'HttpTrigger'] ['in.mp4', '__pycache__', 'sample.dat', 'host.json', 'function.json', '__init__.py'] 在浏览器中与我在 MyFunctionProj

中的相同
  1. 我发现 MyFunctionProj 文件夹中的所有内容都会上传到 Azure 并调用 os.listdir() 显示 MyFunctionProj 的文件列表,所以Python中的当前路径与本地的MyFunctionProj相同。然后我尝试通过下面的代码在本地 Windows 环境中调用 ffmpeg

    def main(req: func.HttpRequest) -> func.HttpResponse:
        if name:
            return func.HttpResponse(f"Hello {name}! {platform.architecture()} {os.listdir()} {os.listdir('HttpTrigger')} {os.path.exists('in.mp4')} {os.popen('ffmpeg.exe -i in.mp4 out.mp4').read()} {os.path.exists('out.mp4')} {os.popen('del out.mp4').read()}")
    
    

    它可以通过命令 ffmpeg.exe -i in.mp4 out.mp4 输出文件 out.mp4,然后考虑将其复制到命令 del out.mp4

  2. 尝试使其适用于 Azure Function 上的 Linux 环境,我将命令更改为 ./ffmpeg -i in.mp4 out.mp4rm out.mp4。但它不适用于 Azure Functions。可能是从Windows上传时缺少ffmpegLinux二进制文件的执行权限造成的。所以我在调用它之前通过命令ls -l ffmpegchmod u+x ffmpeg进行了检查。

    def main(req: func.HttpRequest) -> func.HttpResponse:
        if name:
            return func.HttpResponse(f"Hello {name}! {platform.architecture()} {os.listdir()}  {os.listdir('HttpTrigger')} {os.popen('ls -l ffmpeg').read()} {os.popen('chmod u+x ffmpeg').read()} {os.popen('ls -l ffmpeg').read()} {os.path.exists('in.mp4')} {os.popen('./ffmpeg -i in.mp4 out.mp4').read()} {os.path.exists('out.mp4')} {os.popen('rm out.mp4').read()}")
    
    

    现在可以使用了,结果如下我把它格式化得很漂亮。

    Hello krishna! // Official sample output
    ('64bit', '') // the Linux platform architecture of Azure Functions for Python 
    ['in.mp4', 'ffmpeg', 'host.json', 'requirements.txt', 'ffmpeg.exe', '.python_packages', 'HttpTrigger']  // file list of MyFunctionProj
    ['in.mp4', '__pycache__', 'sample.dat', 'host.json', 'function.json', '__init__.py'] // file list of HttpTrigger
    -r--r--r-- 1 root root 69563752 Nov 10  2021 ffmpeg // before chmod u+x
    -rwxr--r-- 1 root root 69563752 Nov 10  2021 ffmpeg // after chmod u+x
    True  // in.mp4 exists
    True // out.mp4 exists before delete it using `rm`