SMIL应用教程

SMIL应用教程

学习WEB多媒体开发的注意了

SMIL(Synchronized Multimedia Intergration Language,同步多媒体集成语言)是一种以简单,易于了解的XML语言
使各种格式的多媒体播放同步的语言。它可以集成到其它XML语言中,其他XML语言也能集成到该语言中,从而强化
XML的”可扩展”特征。
如果你使用过HTML,就会习惯于SMIL语法,至少一开始是这样。如果你未使用过HTML,但从本教程了解XML,你也会发
现该词汇是较容易的一种。
SMIL能用于控制从源流进的媒体,如RealAudio和RealVideo以及各种其他媒体格式,包括图像,文本,声音和视频

SMIL语法
     最基本的SMIL表示就像创建一个简单HTML页一样简便,观察以下代码看看我们的意图是什么
     <smil>
         <body>
             <audio src=”rstp://realserver.javertising.com/jt01.rm”/>
             <audio src=”rstp://realserver.javertising.com/jt02.rm”/>
             <audio src=”rstp://realserver.javertising.com/jt03.rm”/>
         </body>
     </smil>
     上述代码只不过列出下载文件时将播出的几个多媒体文件
     与所有XML文档一样,有一个根元素,在本例中,根元素是smil。SMIL文档必须遵守所有其他XML规则,其中一些在SMIL
规范中定义,与XML1.0规范一致。所有元素名均小写,自然属性值必须有引号中,对”(引号),&,(省略号),<(左尖括号)和>(右
尖括号)必须使用字符引用。  
     根据SMIL规范,SMIL文档的body元素是必不可少的。如果愿意,可以包含一个head元素,但不做要求:
     <smil>
         <head><!–this is an optional element–></head>
         <body><!–this is a required element–></body>
     </smil>
     创建你的第一个SMIL作品以后,可以用smi或smil扩展名保存该文件。
    
     顺序标注(seq)用于标记你希望顺序播出的元素,而并行标注用于标记你希望并发播出的元素。考虑以下简单标记:
     <seq>
        <audio src=”mySong.rm”/>
        <audio src=”yourSong.rm/>
     </seq>
     上述代码将强迫媒体播放机播放列出的第一首歌,在第一首歌播完之后播放下一首歌。
     你可能不打算并行地播放音乐,但你可能想在播放音乐时显示描述该音乐作品的文本:
     <par>
        <audio src=”mySong.rm”/>
        <textstream src=”songDesc.rt”/>
     </par>
     注意rt和rm扩展。这些是RealMedia格式.
     SMIL的一个有趣方面是,媒体内容的类型不是得自元素名,而是来自服务器,操作系统或元素的type属性,后者定义
MIME类型
     如果你希望在文档中引用SMIL DTD代码应是这样的:
     <!DOCTYPE smil PUBLIC “-//W3C//DTD SMIL 1.0//EN”
                    “http://www.w3.org/TR/REC-smil/SMIL10.dtd“>
     不过,注意SMIL不允许你利用实体说明扩展DTD。
    
     以下几节介绍SMIL元素,它们的属性,它们可能的内容及它们的父代元素。本教程末尾,你将找到一个完事的SMIL文档.

a
  
   a元素是一个链接,它对同步化不起任何作用,只是链接其他资源的一种手段而已。该元素就像HTML a元素一样,主要是因为
属性表包含show属性,它描述a元素所指向资源的不同替换模式。另一个区别是不使用它链接文本(因为文本是一种媒体源)。确
实,你把媒体源隐藏在标注中,如例子所示。
   属性
      id 惟一地确定文档内的元素。其值是XML标识符和ID属性类型
      href 一个包含链接目的地URI的必不可少的属性
      show 控制链接在三种可能模式之间的链接活动:replace(意思是当前表示由被链接对象替代),new(意思是被链接对象作为新
           对象开始)和pause(意思是包含链接的表示暂停,被链接对象在一个新环境下开始被链接的表示完成播放后,被暂停的表示
           重新开始)
内容
      animation,audio,img,par,ref,seq,switch,text,textstream和video元素

   父代元素
      body,par,seq和switch元素
     
例:
    在本例中,链接作为推进到文档另一部分的一种手段。关于链接如何在一个完整文档中动作的例子,见程序清单,在该程序清单中
a元素将幻灯片放映从一幡幻灯片推进到另一幅。它是这样实现的:借助指向文件(pictures.smi,在本例中,恰好是包含链接的同一文件)的
链接,然后利用一个标识符(#)引用该文件内的一个特定元素,在本例中,是id属性值为slide1的一个par元素
    <a href=”pictures.smil#slide1″ show=”replace”>
         <img id=”NavRintro” region=”RButtonRegion” src=”rArrow.jpg” repeat=”1″ fill=”remove”/>
    </a>

anchor
    此元素使你链接一个元素的各部分,类似于HTML中使用图像变址图的方式。该元素的关键是coords属性,它定义链接所指部分的坐标集。

   属性
       begin 指定元素开始状态的时间,借助两个可能值:delay-value(该值度量表示时间)和event-value(这是一个事件触发器)
       coords 指定一个对象显示区内的矩形坐标集
       end 指出元素的明确结束(使用与开始元素相同的值)
       id 惟一确定文档内的元素.它的值是一个XML标识符和一个ID属性类型
       show 控制链接在三种可能模式之间的链接活动:replace(意思是当前表示由被链接对象替代),new(意思是被链接对象作为新
           对象开始)和pause(意思是包含链接的表示暂停,被链接对象在一个新环境下开始被链接的表示完成播放后,被暂停的表示
           重新开始)
       skip-content 用于管理未来SMIL版本元素,借助两个值:true或false.如果是true,则忽略该元素.
       title 一个属性,用于以某种意义的方式命名一个元素,该元素可能被播放器以某种方式显示
    内容
       这是一个空元素
    父代元素
       animation,audio,img,ref,text,textstream和video元素周期律
例:
    本例创建一个视频内的图像映射图。活动链接区由coords属性指定的坐标定义
    <video src=”myVideo.rm” region=”RegionId”>
         <anchor href=”http://www.javertising.com” show=”pause” coords=”10,30,70,100″ begin=”5s” end=”30s”/>
    </video>

animation
   
    这是一个定义动画的连续媒体元素,与其他媒体元素一样,媒体播放器不是通过元素名是借助元素的属性(如type属性,它
给媒体播放器提供元素的MIME类型)提供的信息来检索关于元素及如何播放它的信息。
属性
     abstract 顾名思义,该属性提供元素内容的简要描述
     alt 指出媒体播放器存取内容不支持该元素时的替代文本
     author 表示内容的作者名
     begin 见anchor元素属性表
     clip-begin 指出子剪贴画的开始,利用下述值的一个,这些值均由这种语法定义:
         clip-beign=”npt=0.1h”,度量单位及其相关值是:
           smpte=”YourTime”或smpte-30-drop=”YourTime”或smpte-25=”YourTime”,其中YourTime等于由时,分和秒表示的时间
          如:clip-begin=”smpte=10:12:33:20″.SMPTE是电影电视工程师协会开发的一种时间标准
           npt(正常播放时间),以常规SMIL时钟值表达的时间
     clip-end 指出子剪贴画的结束,利用与clip-begin相同的值。如果其值超出媒体对象的持续时间,则忽略该值
     copyright 包含元素内容的版权声明
     dur 指出一个元素的持续时间
     end 见anchor元素属性表
     fill 控制子元素的持续时间,借助两个值:remove和freeze.其细节取决于在那里使用什么元素
     id 惟一确定文档内的元素。它的值是个XML标识符和一个ID属性类型
     longdesc 包含指向一个媒体对象的冗长的描述的URI
     src 指定媒体对象的URI
     system-bitrate 规定近似带宽,以每秒位为单位(例如,如果预期用户机器上使用56K MODEM,则属性值对应是:system-birate=”56000″)
     system-cpations 就像on或off属性值指示的那样控制字幕选项
     system-language 逗号分界的语言列表,由RFC1766或代码定义(例如,system-language=”ja”表示系统语言是日语)
     system-overdub-or-caption 借助两个值overdub或caption中的一个确定使用配音还是字幕.
     system-required 指出扩展名
     system-screen-size 利用如下所示属性值对指出屏幕大小:system-screen-size=”1024X768″
     system-scrren-depth 提供显示元素时需要的屏幕调色板深度的信息,以位为单位,一般使用下述值之一:1,8,16,24或32,指派32深度
     title 提供为元素赋予有意义名字的一条行径
     type src属性引用的媒体对象的MIME类型

内容
      anchor元素
父代元素
      a,body,par,seq和switch元素(最后一个元素对控制屏幕深度和大小特别重要)
      <smil>
          <body>
             <par>
                 <animation src=”rstp://realserver.javertising.com:554/media.swf”/>
              </par>
           </body>
      </smil>

2、 时间控制
(1)dur属性
请大家看看下面这段代码的效果。
< smil>
< head>
< /head>
< body>
< seq>
< img src=”image1.jpg” dur=”5s”/>
< img src=”image2.jpg” dur=”10s”/ >
< /seq>
< /body>
< /smil>
相信大家已经看出门道了!对了,我们这里对image1.jpg和image2.jpg的持续时间做了规定。其中image1.jpg持续时间5秒,image2.jpg持续时间10秒。
(2)begin和end属性
上面规定的是播放多长时间,我们也想规定在什么时候开始播放。请看下面的程序。
< smil>
< head>
< /head>
< body>
< img src=”image1.jpg” begin=”2″ dur=”5s”/>
< /body>
< /smil>
上面的这段程序规定就是图片image1.jpg在整个演示进行2秒后,开始显示,持续的时间是5秒。对于图片的控制是这样,而我们常常需要对视频/音频的时间进行控制。下面这个例子来说明这个问题。
< smil>
< head>
< /head>
< body>
< video src=”test.rm” begin=”5s” end=”40s”/>
< /body>
< /smil>
test.rm这个视频文件(如果大家手头上没有*.rm格式文件,就用Realone player的firstrun.rm或者找个*.avi的也可以。但是文件名要写对!)在整个演示开始5秒后开始播放,在整个演示播放40秒以后,就结 束播放。实际的播放时间是:40-5=35秒。但是,一般情形下,我们的视频总在一个组中,这时候,他就的服从组的时间了。我们那下面的这个例子来解释这 问题。
< smil>
< body>
< seq dur=”5″>
< img src=”image1.jpg” begin=”2″ dur=”10″/>
< /seq>
< /body>
< /smil>
image1.jpg所在的组的持续时间为5秒,而image1.jpg自己要求持续10秒,这是不行的。实际上image1.jpg的显示时间只有5-2=3秒!大家在以后写程序的时候要注意这个问题。
(3)clip-begin和clip-end属性
考虑这样一种效果:
我们只要test.rm播放这个视频/音频的5~10秒这个时间断,怎么办???J有了clip-begin和clip-end,问题就很简单了!
请看:
< smil>
< body>
< video src=”test.rm” clip-begin=”5s” clip-end=”10s”/>
< /body>
< /smil>
clip-begin和clip-end属性是用内部时间控制的属性。这里的内部指的就是多媒体片断自己的时间线(timeline)。前者规定在什么地方开始播放,后者规定放到什么地方结束播放。为了更清楚的理解这些时间控制,我们看下面的这个例子:
< smil>
< body>
< par>
< audio src=”testone.rm” clip-begin=”5″ dur=”10s”/>
< audio src=”testtwo.rm” begin=”7s” clip-begin=”2s”clip-end=”15s”/>
< /par>
< /body>
< /smil>
看看下面这个示意图:
显然,首先是testone.rm从自己的5秒处开始播放,播放7秒以后,testtwo.rm从自己的2秒处开始与testone.rm一起播放, testone.rm播放到自己得15秒处停止播放,testone.rm播放了15-5=10秒。testtwo.rm播放到自己得15秒处停止播放, testone.rm播放了15-2=13秒。图中灰色(黄色)部分表示播放的部分。
接下来我们对时间的表示方法做个说明(默认的时间是秒,所以”2s” 、”2.0s”和”2″都是一样的 ):
时间标记 指代 例子 说明
h 小时 1.5h 1小时30分钟
min 分钟 4.75min 4分45秒
s 秒 10.45 10秒450毫秒
正确的时间写法是: hh:mm:ss.xy。hh表示小时;mm表示分钟;ss表示秒;x表示1/10秒;y表示1/100秒。例如:begin=”01:40.0″表示的是1分40秒处开始,而begin=”01:40″表示的是1小时40分处开始。真的注意呀J。
时间控制非常重要,它直接影响我们演示的效果。而我们上面讲的这部分是最重要的,所以大家一定要理解上面的各个时间概念及其含义。
(4)fill属性
当演示中的某个片断播放完成以后,我们可以用fill属性来规定它的显示状态。简单的说就是我们是清屏还是冻结屏幕。看下面这个例子:
< smil>
< body>
< video src=”test.rm” dur=”30s” fill=”freeze”/>
< /body>
< /smil>
假设test.rm的长度是20秒,那么我们这里规定的就是:在test.rm播放终了以后,屏幕上显示的是test.rm的最后一帧(通俗的说就是最后一幅画面),显示的时间是30-20=10秒;如果是图片的话,那么显示就是图片。
Fill属性只有remove和freeze两个,默认的值为remove。建议大家在演示的最后的一个多媒体片断上用冻结(freeze),以防止屏幕上空空如也!J
(5)repeat属性
如果我们希望我们演示中的某个片断或者全部的片断重复播放若干次(姑且设为2次)。那么我们可以后用repeat属性来实现该效果。分析下面这个例子:
< smil>
< body>
< vedio src=”test.rm” dur=”1min” repeat=”2″/>
< /body>
< /smil>
上面这个例子就是让test.rm播放两次。如果我们想让某个片断一直播放下去(网络光广告上可以考虑这个),那么repeat= “indefinite”就可以了。当然,想要它停下来的一种方法是按下播放器stop(停止)键(在网页插件中就是右键菜单中的stop);另外的一种 办法(大家都知道的)是关闭计算机!
4、链接制作
传统的流媒体的最大的一个弊端是没有交互性(Interaction)。现在如日中天的flash本质上就是一种可交互性的流!由此可见可交互性的流的市 场潜力。而SMIL是解决大部分流媒体交互性的最好的工具!这部分要求大家必须掌握,如果没有的话,那么我们学习SMIL就失去了意义。因为这里是 SMIL的主要特色(与其他的视频编辑软件相比较),就好像指针是C语言的特色一样。
(1)< a>< /a>标记
运行下面这个程序:
< smil>
< head>
< layout>
< root-layout width=”300″ height=”300″/>
< region id=”videoregion” top=”0″ left=”0″ width=”300″ height=”300″/>
< layout>
< /head>
< body>
< a href=”1.rm”>
< video src=”videotest.rm” region=”videoregion”/>
< /a>
< /body>
< /smil>
正常情况下,我们看到播放器播放videotest.rm,如果我们把鼠标放到正在播放的videotest.rm上面,鼠标将有指针形状变为小手形状。 单击鼠标左键,播放器播放将停止播放videotest.rm而播放1.rm这个文件。这里我们就成功的创建了一个很简单的链接。<a> </a>属性就是用于链接标记,href表示的是所要链接的文件。这种方法非常简单,我们就不做过多的介绍。
如果我们要创建更加复杂的链接,我们就要用到下面的这个属性。
(2)< anchor>属性
将上例中的< body>< /body>换成下面这段代码,看看效果是不是有区别?
< body>
< video src=”videotest.rm” region=”videoregion”>
< anchor href=”1.rm”/>
< /video>
< /body>
我们看到的效果是完全一样的!那么<anchor>属性不就多余了吗? 那是不会的!JJ请看:
a、 分时断链接
考虑这样一个问题:我们要在0~10秒链到一个文件,10~20秒链到另一个文件,该怎么办?看我们的:
< body>
< video src=”1.avi” region=”videoregion”>
< anchor href=”1.jpg” begin=”0s” end=”10s” >
< anchor href=”videotest.rm” begin=”10s” end=”20s” />
< /video>
大家将看到的效果:播放器播放1.avi,在0~10秒链到1.jpg,在10~20秒链到videotest.rm。警告:dur、clip-begin和clip-end这里不支持!
B、链接部分SMIL
我们的链接可以链接的文件很多,几乎所用的多媒体片断都可以。*.smil和*.html也可以。但是,下面我们要讨论的是如何链接部分SMIL。请看例子。
第一个SMIL文件,取名test11.smil
< smil>
< head>
< layout>
< root-layout width=”400″ height=”300″/>
< region id=”videoregion” top=”0″ left=”0″ width=”400″ height=”300″ fit=”meet”/>
< /layout>
< /head>
< body>
< video src=”1.avi” region=”videoregion”>
< anchor href=”test11app.smil#testlink”/>
< /video>
< /body>
< /smil>
第一个SMIL文件,取名test11app.smil
< smil>
< head>
< layout>
< root-layout width=”400″ height=”300″/>
< region id=”videoregion” top=”0″ left=”0″ width=”400″ height=”300″ fit=”meet”/>
< /layout>
< /head>
< body>
< video id=”testlink” src=”1.avi” clip-begin=”150″ region=”videoregion”/>
< /body>
< /smil>
大家一定看出来了!我就是在test11app.smil中为我们要链接的那部分内容设上id,然后在test11.smil中的链接中用“#”来指向该标记id。应用的很多的时候是组内内容。我们把test11app.smil修改为:
< body>
< par id=”testlink”>
< video src=”1.avi” clip-begin=”150″ region=”videoregion”/>
< /par>
< /body>
到这里,链接可以说已经很完美了。但是,如果要锦上添花,那么下面这个属性是必不可少的。
(3)coords属性
将上面的<anchor href=”1.rm”/>代码修改为:
< anchor href=”1.rm” coords=”0, 0,150,300″/>
或者:
< anchor href=”1.rm” coords=”0%, 0%,50%,100%”/>
运行,看看效果。JJ我们看到左半部分有链接效果,而右半部分却没有!这是我们采用了坐标规定链接区的缘故。coords属性值的第一、二个数分别表示的 是链接区的左上角点的水平(left)和垂直(top)坐标;第三、四个数分别表示的是链接区的右下角点的水平(left)和垂直(top)坐标。上面用 的是像素点的绝对定义方法,下面用的是比例的相对定义方法。喜欢哪一个就看你的喜好了。
(5)链接注意
我们的演示最后基本上都要放到服务器上。因此,文件的位置的规定就非常重要,如果文件位置出错,那么播放器将找不到文件而不能播放。这是我们最不希望看到的!下面我们就来讨论这个问题。
A、创建基地址
看下面的代码:
< head>
< meta name=”base” content=”rtsp://abc.5dmedia.com/”/>
< /head>
上面就是在< head>< /head>中用附加信息的方式规定了整个smil文件的基地址为rtsp://abc.5dmedia.com/。规定了基地址以后,我们在用该地址下的文件的时候,就只需要给出路径就可以了。例如:
< body>
< video src=”video/first.rm”/>
< video src=” video /second.rm”/>
< audio src=”rtsp:// abc.mysite.com:554/audio/test.mp3″/>
< img src=”http// www.5dmedia.com/image/welcome.jpg”/>
< /body>
这个例子中的前面的两个文件用的是基地址服务器上的文件,所以,可以之写出相对地址。但是,后面的两个文件用的是其他服务器上的文件,我们必须给出绝对地 址。其中rtsp是实时流传输协议,它保证SMIL播放器正确地从流服务器abc.mysite.com上的audio文件夹下获得我的所要的文件 test.mp3。554为流服务器的端口。http是超文本传输协议。它保证SMIL播放器正确地从web服务器www.5dmedia.com上 的image文件夹下获得我的所要的文件welcome.jpg。< audio src=”rtsp:// abc.mysite.com:554/audio/test.mp3″/>说明的是该文件不在上面的基地址下,而在rtsp:// abc.mysite.com:554/audio/这个地方法,所我们必须修改地址。
如果我们用的是本地机器硬盘上的文件就可以用src=”file:/c:/audio/first.rm”进行读取该文件。
大家在调用文件之前,一定要弄清楚文件的位置!

7、 转场效果

首先解释一下什么是转场效果。我们的演示中多媒体片断是很多的,不可避免的会有两个片断之间的切换。例如:一个图片演示完了,该接着演示下一个图 片,两图片中间是有一个过渡的。这个过渡我们就称谓转场效果。如果我们不设置转场效果,那么,过渡的效果肯定不好。LSMIL中的转场效果大致分为 wipe和fade两类。
(1) fade类型
从名字就可以看出,这个是淡入淡出的效果。先睹为快!J 请看例子!
< smil xmlns=”http://www.w3.org/2001/SMIL20/Language“>
< head>
< transition id=”fade1″ type=”fade” subtype=”fadeToColor” dur=”4s” />
< transition id=”fade2″ type=”fade” subtype=”fadeFromColor” dur=”4s” />
< /head>
< body>
< img src=”g04.jpg” dur=”10s” transIn=”fade2″ transOut=”fade1″/>
< /body>
</smil>
解释:a、transition声明我们要设置转场效果。id=”fade1″设置了该转场效果的id号。id号必须设置。type=”fade”设置了 转场效果的基本类型为fade。 subtype=”fadeToColor”设置了转场效果的具体类型(子类型)为fadeToColor(注意这里又是我们提到的骆驼写法!)。dur =”4s”设置了该场效果完成的时间。
b、transIn=”fade2″设置了图片g04.jpg显示时采用转场效果fade2; transOut=”fade1″规定图片g04.jpg完成显示时采用转场效果fade1。
c、fade只有三个子类型。上面我们用了2个。还有一个是crossfade,这个也是缺省设置。
(2) wipe类型
wipe为擦去类型。该类型的效果很多很多。我们这里所说的wipe只是他们的总称(注意wipe不能作为type的属性值,而是它的子类作为type的 属性值,子类的子类作为subtype的属性值!J谁让它的属性值这么多!!!)。具体的有barWipe、boxWipe、fourBoxWipe等 36大类!!!不管它有多少类,先看看怎么弄。请看例子:
< smil xmlns=”http://www.w3.org/2001/SMIL20/Language“>
< head>
< transition id=”wipe1″ type=”slideWipe” subtype=”fromTop”/>
< transition id=”wipe2″ type=”waterfallWipe”/>
< /head>
< body>
< img src=”g03.jpg” transIn=”wipe1″ transOut=”wipe2″ dur=”5s”/>
< /body>
< /smil>
解释:a、JJJ和上面的写法基本上是一致的!
b、type=”waterfallWipe”后面没有子类型表示使用的是waterfallWipe类型的默认子类型。
(3) 综合应用
我们上面都只是用在单个多媒体片断上的转场效果。下面看看在多个多媒体片断上怎样设置转场效果。还得看例子:J
< smil xmlns=”http://www.w3.org/2001/SMIL20/Language“>
< head>
< layout>
< root-layout width=”400″ height=”300″/>
< /layout>
< transition id=”fade” type=”fade” subtype=”fadeToColor” fadeColor=”green” dur=”4s”/>
< transition id=”fade1″ type=”fade” subtype=”fadeFromColor” fadeColor=”red” dur=”4s”/>
< transition id=”fade2″ type=”fade” subtype=”crossfade” dur=”2s”/>
< transition id=”push” type=”snakeWipe” dur=”4″ />
< /head>
< body>
< seq>
< img dur=”5s” src=”g06.jpg” transIn=”fade1″ fill=”transition”/>
< img dur=”4s” src=”g05.jpg” transIn=”fade2″ fill=”transition”/>
< img dur=”4s” src=”g06.jpg” transIn=”fade2″ fill=”transition”/>
< img dur=”4s” src=”g05.jpg” transIn=”push” transOut=”fade”/>
< /seq>
< /body>
< /smil>
解释:a、fadeColor=”green”设置了谈出谈入色为绿色(green)。在这里表示的就是从当前的多媒体片断渐变为绿色。下面的fadeColor=”red”则表示从红色渐变为当前的多媒体片断(如果是图片则变为图片,如是视频则变为第一帧)。
b、fill=”transition”表示的是最后的完成效果有下面的转场效果来决定。
c、最后一个就不能用fill=”transition”了。想想,它就是最后一个了,上哪里去找下面的转场效果呢?

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100591.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号