<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>格式转换 on 豆子技术站</title><link>https://blog.91demo.top/tags/%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2/</link><description>Recent content in 格式转换 on 豆子技术站</description><generator>Hugo -- 0.155.1</generator><language>zh-cn</language><lastBuildDate>Fri, 05 Jan 2018 12:40:16 +0800</lastBuildDate><atom:link href="https://blog.91demo.top/tags/%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2/index.xml" rel="self" type="application/rss+xml"/><item><title>实战笔记：为了省下服务器流量费，我给小程序加上了 Webp 转换</title><link>https://blog.91demo.top/image-convert/</link><pubDate>Fri, 05 Jan 2018 12:40:16 +0800</pubDate><guid>https://blog.91demo.top/image-convert/</guid><description>&lt;p&gt;在“流量贵如油”的今天，作为一名自己买服务器、撸代码的站长，如何给服务器“减负”是每天都要思考的必修课。&lt;/p&gt;
&lt;h3 id="痛点博客网站的流量杀手"&gt;痛点：博客网站的流量杀手&lt;/h3&gt;
&lt;p&gt;我有一个运行多年的个人博客。在分析服务器日志时发现，最大的流量开销并不是文字，而是文章里那些高清的图片。&lt;/p&gt;
&lt;p&gt;虽然 JPG 和 PNG 已经很普及，但随着屏幕分辨率越来越高，原图动辄几 MB，对于按带宽付费或者流量计费的服务器来说，这都是白花花的银子。&lt;/p&gt;
&lt;h3 id="方案webp-格式的降维打击"&gt;方案：Webp 格式的“降维打击”&lt;/h3&gt;
&lt;p&gt;现在主流浏览器（Chrome, Safari, Edge 等）已经全面支持 &lt;strong&gt;Webp&lt;/strong&gt; 格式。相比于传统的 JPG 和 PNG，Webp 可以在保证肉眼看不出画质损失的前提下，将文件体积&lt;strong&gt;压缩 30% 到 70%&lt;/strong&gt;。这是一个非常惊人的数据。这意味着原本 100GB 的图床流量，换成 Webp 后可能只需要 30GB。&lt;/p&gt;
&lt;p&gt;为了方便处理博客素材，我决定把这个需求也集成到“豆子工具”里。&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片格式转换" loading="lazy" src="https://blog.91demo.top/images/wander/image-convert.webp"&gt;&lt;/p&gt;
&lt;h3 id="实现基于-google-官方工具链"&gt;实现：基于 Google 官方工具链&lt;/h3&gt;
&lt;p&gt;图片转换的实现原理与我之前的“音频转换”方案异曲同工，主打一个&lt;strong&gt;稳定与高效&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;核心引擎&lt;/strong&gt;：在服务端安装了 Google 官方出品的 &lt;code&gt;webp&lt;/code&gt; 命令行工具链（&lt;code&gt;cwebp&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;后端调度&lt;/strong&gt;：依然由 &lt;strong&gt;Go&lt;/strong&gt; 语言担任“指挥官”，接收小程序上传的 PNG/JPG 原图，调用外部 &lt;code&gt;cwebp&lt;/code&gt; 进程进行压缩。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;参数优化&lt;/strong&gt;：在后端我预设了平衡性最好的质量参数，确保图片在压缩后的清晰度依然能够满足博客展示的需求。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;闭环应用&lt;/strong&gt;：现在我写每一篇博客前，都会先用小程序把配图过一遍，转成 Webp 后再上传。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面是核心代码片段的注解，这是小程序端：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;page-meta root-font-size=&amp;#34;system&amp;#34; /&amp;gt;
&amp;lt;view class=&amp;#34;page&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;page__hd&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;page__title&amp;#34;&amp;gt;图片格式转换&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;page__desc&amp;#34;&amp;gt;可将图片转换为WebP格式，用于Web项目。&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;page__bd&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-cells weui-cells_radio&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell weui-cell_uploader&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell__bd&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-uploader&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-uploader__hd&amp;#34;&amp;gt;
&amp;lt;view aria-role=&amp;#34;option&amp;#34; class=&amp;#34;weui-uploader__overview&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-uploader__title&amp;#34;&amp;gt;图片信息&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-uploader__tips&amp;#34;&amp;gt;
请选取5M内的图片，目前仅支持一张
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-uploader__bd&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-uploader__files&amp;#34; id=&amp;#34;uploaderFiles&amp;#34;&amp;gt;
&amp;lt;block wx:for=&amp;#34;{{files}}&amp;#34; wx:key=&amp;#34;*this&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-uploader__file&amp;#34; bindtap=&amp;#34;previewImage&amp;#34; id=&amp;#34;{{item}}&amp;#34;&amp;gt;
&amp;lt;image class=&amp;#34;weui-uploader__img&amp;#34; src=&amp;#34;{{item}}&amp;#34; mode=&amp;#34;aspectFill&amp;#34; /&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/block&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-uploader__input-box&amp;#34;&amp;gt;
&amp;lt;view aria-role=&amp;#34;button&amp;#34; aria-label=&amp;#34;选择图片&amp;#34; class=&amp;#34;weui-uploader__input&amp;#34; bindtap=&amp;#34;chooseImage&amp;#34;&amp;gt;&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell&amp;#34;&amp;gt;
&amp;lt;view wx:if=&amp;#34;{{headImageExist}}&amp;#34;&amp;gt;
&amp;lt;image style=&amp;#34;width: 200px; height: 200px; background-color: #eeeeee;&amp;#34; mode=&amp;#34;aspectFit&amp;#34; src=&amp;#34;{{headImage}}&amp;#34; bindtap=&amp;#34;previewMakeImage&amp;#34;&amp;gt;&amp;lt;/image&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view wx:else&amp;gt;&amp;lt;text&amp;gt;转换完成的图片会展示在这里&amp;lt;/text&amp;gt;&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;button-sp-area&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-btn weui-btn_primary weui-wa-hotarea&amp;#34; aria-role=&amp;#34;button&amp;#34; bindtap=&amp;#34;imageConvert&amp;#34;&amp;gt;开始转换&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-btn weui-btn_warn weui-wa-hotarea&amp;#34; aria-role=&amp;#34;button&amp;#34; bindtap=&amp;#34;saveToPhotosAlbum&amp;#34;&amp;gt;保存到相册&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面是界面骨架，现在说下它的灵魂。首先通过小程序的上传文件API，wx.uploadfile将图片文件上传到服务器，然后使用Go调用cwebp进行格式转换，转换成功后，下载文件到小程序本地，然后删除服务器端的文件。&lt;/p&gt;</description></item><item><title>实战笔记：我把 FFmpeg 搬进小程序，搞定了音频格式转换</title><link>https://blog.91demo.top/audio-convert/</link><pubDate>Thu, 04 Jan 2018 12:40:16 +0800</pubDate><guid>https://blog.91demo.top/audio-convert/</guid><description>&lt;p&gt;在“豆子工具”众多的功能里，&lt;strong&gt;音频转换（m4a 转 mp3）&lt;/strong&gt; 是我使用频率最高、也最具有“个人救赎”色彩的一个。&lt;/p&gt;
&lt;h3 id="起因被软件更新背刺后的郁闷"&gt;起因：被软件更新“背刺”后的郁闷&lt;/h3&gt;
&lt;p&gt;这个功能的由来非常接地气：有一段时间，我需要频繁地将苹果手机录音产生的 &lt;code&gt;m4a&lt;/code&gt; 格式文件转换成 &lt;code&gt;mp3&lt;/code&gt;，因为当时某个必须使用的业务软件只认 &lt;code&gt;mp3&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;那时候我找遍了各种转换工具。最后发现某款主流音乐软件自带的转换功能挺好用。然而，好景不长，在一次软件自动更新后，这个功能竟然被砍掉了。我去搜老版本安装包，却发现根本找不到安全的下载路径。&lt;/p&gt;
&lt;p&gt;那种“被绑架”的无奈感，相信每个工具控都深有体会。&lt;/p&gt;
&lt;h3 id="进阶大名鼎鼎的-ffmpeg"&gt;进阶：大名鼎鼎的 ffmpeg&lt;/h3&gt;
&lt;p&gt;郁闷之后，我转向了技术人的终极方案——&lt;strong&gt;ffmpeg&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;命令行虽然硬核，但确实强大到无以复加。一条简单的指令就能解决所有问题：&lt;br&gt;
&lt;code&gt;ffmpeg -i input.m4a output.mp3&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;用了很长一段时间的命令行后，新的问题又来了，一次在外面，突然用户需要转换音频，我总不能随时随地都带着电脑吧？于是，我动了把 ffmpeg 搬进“豆子工具”的心思。&lt;/p&gt;
&lt;h3 id="实现极简架构下的随时随地"&gt;实现：极简架构下的“随时随地”&lt;/h3&gt;
&lt;p&gt;在小程序里实现这个功能，原理其实并不复杂，核心在于&lt;strong&gt;后端调度&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;前端上传&lt;/strong&gt;：小程序端选择 &lt;code&gt;m4a&lt;/code&gt; 文件，上传至服务器。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;后端处理&lt;/strong&gt;：后端使用 &lt;strong&gt;Go&lt;/strong&gt; 语言接收文件，通过 &lt;code&gt;exec&lt;/code&gt; 模块调用服务器系统环境中的 &lt;code&gt;ffmpeg&lt;/code&gt; 进程进行转换。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时试听&lt;/strong&gt;：为了保证体验，我在小程序里集成了一个音频播放器。转换前可以听一下是否选对了文件，转换后也可以即时试听确认效果。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;即用即删&lt;/strong&gt;：转换生成的文件在用户下载后会立即从服务器删除，既保护了隐私，也完全不占用宝贵的服务器存储空间。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面是核心代码片段的注解，这是小程序端：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;page-meta root-font-size=&amp;#34;system&amp;#34; /&amp;gt;
&amp;lt;view class=&amp;#34;page&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-form&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-form__text-area&amp;#34;&amp;gt;
&amp;lt;h2 class=&amp;#34;weui-form__title&amp;#34;&amp;gt;音频格式转MP3&amp;lt;/h2&amp;gt;
&amp;lt;view class=&amp;#34;weui-form__desc&amp;#34;&amp;gt;因微信限制，保存文件即为分享文件，可通过微信文件传输助手下载文件。目前仅支持以下格式（M4A、WAV、AMR）文件转换为MP3文件。&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-form__control-area&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-cells__group weui-cells__group_form&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-cells weui-cells_radio&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell weui-cell_active weui-cell_vcode weui-cell_wrap&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell__hd&amp;#34;&amp;gt;&amp;lt;label class=&amp;#34;weui-label&amp;#34;&amp;gt;文件&amp;lt;/label&amp;gt;&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell__bd&amp;#34;&amp;gt;
&amp;lt;input class=&amp;#34;weui-cell__control weui-cell__control_flex weui-input&amp;#34; type=&amp;#34;text&amp;#34; placeholder=&amp;#34;请选取5M内的音频&amp;#34; placeholder-class=&amp;#34;weui-input__placeholder&amp;#34; value=&amp;#34;{{filename}}&amp;#34; /&amp;gt;
&amp;lt;view aria-role=&amp;#34;button&amp;#34; class=&amp;#34;weui-cell__control weui-btn weui-btn_default weui-vcode-btn&amp;#34; bindtap=&amp;#34;chooseMedia&amp;#34;&amp;gt;选择&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell&amp;#34;&amp;gt;
&amp;lt;view wx:if=&amp;#34;{{audioExist}}&amp;#34;&amp;gt;
&amp;lt;audio name=&amp;#34;{{filename}}&amp;#34; src=&amp;#34;{{filepath}}&amp;#34; id=&amp;#34;myAudio&amp;#34; controls&amp;gt;&amp;lt;/audio&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view wx:else&amp;gt;&amp;lt;text&amp;gt;选择音频文件后可以在这里试听&amp;lt;/text&amp;gt;&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-cell&amp;#34;&amp;gt;
&amp;lt;view wx:if=&amp;#34;{{makeAudioExist}}&amp;#34;&amp;gt;
&amp;lt;audio name=&amp;#34;{{makeAudioName}}&amp;#34; src=&amp;#34;{{makeAudioPath}}&amp;#34; id=&amp;#34;myAudio&amp;#34; controls&amp;gt;&amp;lt;/audio&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view wx:else&amp;gt;&amp;lt;text&amp;gt;转换完成的文件会展示在这里&amp;lt;/text&amp;gt;&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-form__opr-area&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;button-sp-area&amp;#34;&amp;gt;
&amp;lt;view class=&amp;#34;weui-btn weui-btn_primary weui-wa-hotarea&amp;#34; aria-role=&amp;#34;button&amp;#34; bindtap=&amp;#34;audioConvert&amp;#34;&amp;gt;开始转换&amp;lt;/view&amp;gt;
&amp;lt;view class=&amp;#34;weui-btn weui-btn_warn weui-wa-hotarea&amp;#34; aria-role=&amp;#34;button&amp;#34; bindtap=&amp;#34;saveFile&amp;#34;&amp;gt;保存文件&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&amp;lt;/view&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面是界面骨架，现在说下它的灵魂。首先通过小程序的上传文件API，wx.uploadfile将音频文件上传到服务器，然后使用Go调用ffmpeg进行格式转换，转换成功后，下载文件到小程序本地，然后删除服务器端的文件。&lt;/p&gt;</description></item></channel></rss>