rubyで指定したディレクトリ内のflvファイルからmp3抽出

require "shell"

FLV_DIR_PATH = "FLVファイル保存ディレクトリ名"
RESULT_DIR = "MP3ファイル保存ディレクトリ名"

CONVERT_SH_FILE_NAME = "convert.sh"

# mp3ファイル生成
def createMp3File(name)
  resultName = toMp3Name(name)
  sh = Shell.new()
  sh.system(FLV_DIR_PATH + "/" + CONVERT_SH_FILE_NAME, name, RESULT_DIR + "/" + resultName)  
end

# flvファイル名からmp3ファイル名生成
def toMp3Name(name)
  lastIndex = name.rindex(".")
  slashIndex = name.rindex("/")
  name = name.slice(0, lastIndex)
  name = name + ".mp3"
  name = name.slice(slashIndex + 1, name.size)
  return name
end

dir = Dir.open(FLV_DIR_PATH)
dir.each{|name|

 if name == "." || name == ".." || name.include?(".sh")
     next
 end
 puts name
 createMp3File(FLV_DIR_PATH + "/" + name)
}


convert.sh

#!/bin/sh
ffmpeg -i $1 -acodec copy $2

GAEサンプル動かすまで

eclipseにpydev pluginインストール済み

Google App Engine SDK for Pythonをダウンロード

プロジェクト新規作成→python→gae application
sdkのフォルダを設定し、適当なプロジェクトテンプレートを選択してプロジェクト作成。

その後で以下を実行
python $SDK_HOME/dev_appserver.py eclipseプロジェクト/src

以下にアクセス
http://localhost:8080/

youtubeだ!

youtube!!

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import gdata.service
import gdata.youtube
import gdata.youtube.service

client = gdata.youtube.service.YouTubeService()
query = gdata.youtube.service.YouTubeVideoQuery()
query.vq = "月食"
query.max_results = "1"
query.racy = "exclude"
query.format = "1"

feed = client.YouTubeQuery(query)

def print_entry(entry):
  print "title: " , entry.media.title.text
  print "youtubu url: " , entry.media.player.url
  print "swf url: " , entry.GetSwfUrl()
  print "view count:" , entry.statistics.view_count
  print "rating: " , entry.rating.average

  for alternate_format in entry.media.content:
    print "-" * 20
    print "format: " , alternate_format.type 
    print "url :" , alternate_format.url
    print "-" * 20

  for thumbnail in entry.media.thumbnail:
    print "thumbnail: " , thumbnail.url

for entry in feed.entry:
    print_entry(entry)





実行結果

title:  皆既月食の動画・16:9版
youtubu url:  http://www.youtube.com/watch?v=4kF7UKX-x2k
swf url:  http://www.youtube.com/v/4kF7UKX-x2k&f=videos&app=youtube_gdata
view count: 55388
rating:  4.3333335
                                      • -
format: application/x-shockwave-flash url : http://www.youtube.com/v/4kF7UKX-x2k&f=videos&app=youtube_gdata
                                      • -
                                      • -
format: video/3gpp url : rtsp://rtsp2.youtube.com/CiILENy73wIaGQlpx_6lUHtB4hMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp
                                      • -
                                      • -
format: video/3gpp url : rtsp://rtsp2.youtube.com/CiILENy73wIaGQlpx_6lUHtB4hMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp
                                      • -
thumbnail: http://i.ytimg.com/vi/4kF7UKX-x2k/2.jpg thumbnail: http://i.ytimg.com/vi/4kF7UKX-x2k/1.jpg thumbnail: http://i.ytimg.com/vi/4kF7UKX-x2k/3.jpg thumbnail: http://i.ytimg.com/vi/4kF7UKX-x2k/0.jpg

flvのurlは取れない!!
もう使わなさそう。



参考:
http://code.google.com/apis/youtube/code.html#sample_code

twistedっていうのを発見!upnp機器検出してみる。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor

# udp_listener
class udp_listener():
    # listen
    def listen(self, datagram, address):
        print "from:", address
        print "datagram: " + repr(datagram)

# MSearchListener
class m_search_listener(udp_listener):
    # listen
    def listen(self, datagram, address):
        print "from address: " , address[0]
        print "from port: " , address[1]
        print "-" * 20
        device = self.__parse(datagram)
        for key in device.keys():
            print key, " = ", device[key]
        
    def __parse(self, datagram):
        values = repr(datagram).split("\\r\\n")
        result = {}
        for value in values:
            datas = value.split(":", 1)
            if datas[0] == "\r\n":
                break
            elif not len(datas) == 2:
                continue
            else:
                result[datas[0]] = datas[1].strip()
        return result
    
class m_search(DatagramProtocol):
    # request   
    M_SEARCH_REQUEST = "M-SEARCH * HTTP/1.1\r\n" + \
                       "MX: 3\r\n" + \
                       "HOST: 239.255.255.250:1900\r\n" + \
                       "MAN: \"ssdp:discover\"\r\n" + \
                       "ST: upnp:rootdevice\r\n\r\n" 
    
    def __init__(self, listener = udp_listener()):
        self.listener = listener

    def datagramReceived(self, datagram, address):
        self.listener.listen(datagram, address)
    
if __name__ == "__main__":
    client = m_search(m_search_listener())
    reactor.listenUDP(0, client).write(m_search.M_SEARCH_REQUEST, ('239.255.255.250', 1900))
    reactor.run()

結果:

from address:  192.168.1.1
from port:  1900
                                      • -
USN = uuid:00000000-0000-0001-0000-000d0b5b0c3c::upnp:rootdevice Server = XXXX/XXXX Release 0023 UPnP/1.0 UPnP-Device-Host/1.0 EXT = Location = http://192.168.1.1:80/xxx.xml Cache-Control = max-age=60 ST = upnp:rootdevice

複数upnp機器あっても大丈夫?
twistedの使い方がよく分からない。

reactor.run()で止まる。止めないことはできる?


参考:
http://code.activestate.com/recipes/425975/

m-searchでupnp機器検出してみる

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import traceback

# m_search
class m_search:
    # M_SEARCH_REQUEST
    M_SEARCH_REQUEST = "M-SEARCH * HTTP/1.1\r\n" + \
                       "MX: 3\r\n" + \
                       "HOST: 239.255.255.250:1900\r\n" + \
                       "MAN: \"ssdp:discover\"\r\n" + \
                       "ST: upnp:rootdevice\r\n\r\n" 
                        
    # BRODCAST_ADDRESS
    BRODCAST_ADDRESS = "239.255.255.250"
    # PORT
    PORT = 1900

    def __init__(self):
        pass
    
    def getDevice(self):
        # getDevice
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.sendto(m_search.M_SEARCH_REQUEST, (m_search.BRODCAST_ADDRESS, m_search.PORT))
        try:
            file = s.makefile()
            return self._parse(file)
        except:
            traceback.print_exc()
        finally:
            file.close()
            s.close()
            
            
    def _parse(self, file):
        # parse
        result = {}
        for line in file:
            if not line:
                break
            else:
                datas = line.split(":", 1)
                if datas[0] == "\r\n":
                    break
                elif not len(datas) == 2:
                    continue
                else:
                    result[datas[0]] = datas[1].strip()
        return result
    
if __name__ == "__main__":
    device = m_search().getDevice()
    for key in device.keys():
        print key, " = ", device[key]
    

実行結果:

USN  =  uuid:00000000-0000-0001-0000-000d0b5b0c3c::upnp:rootdevice
Server  =  XXXX/XXX Release 0023 UPnP/1.0 UPnP-Device-Host/1.0
EXT  =  
Location  =  http://192.168.1.1:80/xxx.xml
Cache-Control  =  max-age=60
ST  =  upnp:rootdevice

TODO: upnp機器が複数あったらダメじゃない?

TkinterよりwxPythonのがいいという噂なのでwxPythonで作成

makarohiraki2009-07-12

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import wx
import wx.lib.mixins.listctrl as listmix
import amazon as az
import sys

# 検索結果表示リスト
class BookList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    def __init__(self, parent, ID, pos=wx.DefaultPosition,
                 size=wx.DefaultSize, style=0):
        wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
        listmix.ListCtrlAutoWidthMixin.__init__(self)


# フレーム
class AmazonBookSearchFrameWx(wx.Frame):
    
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(750, 300))
        
        # パネル
        panel = wx.Panel(self, -1)
        
        # 入力
        self.text = wx.TextCtrl(panel, 2, "ここにタイトル入力!", size = (250, 30))
        self.text.Bind(wx.EVT_SET_FOCUS, self.textClear, id = self.text.GetId())
        # ボタン
        self.button = wx.Button(panel, 1, "検索")
        self.button.Bind(wx.EVT_BUTTON, self.submit, id = self.button.GetId())
        
        # リスト
        self.list = BookList(self, 3, size = (730, 200)
                             ,style=wx.LC_REPORT 
                             | wx.LC_SORT_ASCENDING
                             | wx.LC_SINGLE_SEL
                             )
        self.__init_book_list()
        
        # レイアウト
        gbs = wx.GridBagSizer(2, 2)
        gbs.Add(self.text, (0,0))
        gbs.Add(self.button, (0,1))
        gbs.Add(self.list, (1,0), (1, 2))
        
        box = wx.BoxSizer()
        box.Add(gbs, 0, wx.ALL, 10)
        panel.SetSizerAndFit(box)
        
        
        self.Centre()
        self.Show(True)

    def __init_book_list(self):
        # リストの初期化
        self.list.InsertColumn(0, "タイトル", wx.LIST_FORMAT_CENTER)
        self.list.InsertColumn(1, "著者", wx.LIST_FORMAT_CENTER)
        self.list.InsertColumn(2, "レビュー", wx.LIST_FORMAT_CENTER)

        self.list.SetColumnWidth(0, 500)
        self.list.SetColumnWidth(1, 100)
        self.list.SetColumnWidth(2, 20)

    def submit(self, event):
        # 前の検索結果削除
        self.list.DeleteAllItems()
        
        param = {az.AmazonClient.TITLE: self.text.GetValue()}
        client = az.AmazonClient(param)
        bookList = client.doRequest()
        
        for book in bookList:
            index = self.list.InsertStringItem(sys.maxint, book.title)
            self.list.SetStringItem(index, 1, book.author)
            self.list.SetStringItem(index, 2, str(book.averagerating))
    
    def textClear(self, event):
        self.text.SetValue("")
        

if __name__ == "__main__":
    app = wx.App()
    AmazonBookSearchFrameWx(None, -1, '本の検索')
    app.MainLoop()

wxPythonはサンプルも多いのでpythonGUIやるならwxPythonで決定。
スクロールも自動的に。
列ごとのサイズの設定もできる。

[参考]
http://zetcode.com/wxpython/

TkinterでGUI作成。

makarohiraki2009-07-09


昨日のAmazonClient使って本を検索。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import Tkinter as Tk
import tktable as ta
import amazon as am

""" AmazonBookSearchFrame"""
class AmazonBookSearchFrame(Tk.Frame):
    
    def __init__(self, master = None):
        Tk.Frame.__init__(self, master)
        self.master.wm_geometry("650x300+250+200")
        self.master.title(u"Amazon 本検索")

        #タイトルラベル
        titleLabel = Tk.Label(self, master, text = u"タイトル入力!!", font=('Helvetica', '10', 'bold'))
        titleLabel.grid(row = 0, column = 0, padx = 0, pady = 0)
        
        #タイトル入力
        self.titleStrVar = Tk.StringVar()
        self.titleInputEntry = Tk.Entry(self, textvariable = self.titleStrVar)
        self.titleInputEntry.grid(row = 1, column = 0, padx = 5, pady = 5)
        
        # 検索ボタン
        button = Tk.Button(self, text="検索", command=self.search, width = 10)
        button.grid(row = 1, column = 1, padx = 5, pady = 5)
        
        # テーブル
        self.tableVar = ta.ArrayVar(self)
        self.__set_table_title()
        table = ta.Table(self,
                             rows=10,
                             cols=3,
                             state='disabled',
                             width=10,
                             height=10,
                             titlerows=1,
                             colwidth=30,
                             variable=self.tableVar,
                             selecttype='row')
        table.grid(row = 2, column = 0, columnspan = 2,  sticky=Tk.W + Tk.E + Tk.N + Tk.S)

    
    def __set_table_title(self):
        # 列名設定
        titles = (u"タイトル", u"評価", u"値段")
        for i in range(len(titles)):
            index = "%d,%d" % (0, i)
            self.tableVar.set(index, titles[i])
        
    def search(self):
        # 検索開始
        param = {am.SearchWordType.TITLE: self.titleStrVar.get()}
        client = am.AmazonClient(param)
        response = client.doRequest()
        
        tableVar = self.tableVar
        if len(response) > 0:
            indexList = []
            for i in range(1, len(response)):
                indexList = ["%d,%d" % (i, x) for x in range(4)]
                print indexList
                tableVar.set(indexList[0], response[i].title)
                tableVar.set(indexList[1], response[i].averagerating)
                tableVar.set(indexList[2], response[i].price + u"円")
                
if __name__ == "__main__":
    main = AmazonBookSearchFrame()
    main.pack()
    main.mainloop()

tktableの使い方がよく分からないので調査中。
もっと色々と細かい設定がしたい。そもそもできるのか?